<!doctype html>
<html>
<head>
<meta charset='UTF-8'><meta name='viewport' content='width=device-width initial-scale=1'>
<title>Linux学习笔记【新】</title><link href='https://fonts.loli.net/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext' rel='stylesheet' type='text/css' /><style type='text/css'>html {overflow-x: initial !important;}:root { --bg-color:#ffffff; --text-color:#333333; --select-text-bg-color:#B5D6FC; --select-text-font-color:auto; --monospace:"Lucida Console",Consolas,"Courier",monospace; }
html { font-size: 14px; background-color: var(--bg-color); color: var(--text-color); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; }
body { margin: 0px; padding: 0px; height: auto; bottom: 0px; top: 0px; left: 0px; right: 0px; font-size: 1rem; line-height: 1.42857; overflow-x: hidden; background: inherit; tab-size: 4; }
iframe { margin: auto; }
a.url { word-break: break-all; }
a:active, a:hover { outline: 0px; }
.in-text-selection, ::selection { text-shadow: none; background: var(--select-text-bg-color); color: var(--select-text-font-color); }
#write { margin: 0px auto; height: auto; width: inherit; word-break: normal; overflow-wrap: break-word; position: relative; white-space: normal; overflow-x: visible; padding-top: 40px; }
#write.first-line-indent p { text-indent: 2em; }
#write.first-line-indent li p, #write.first-line-indent p * { text-indent: 0px; }
#write.first-line-indent li { margin-left: 2em; }
.for-image #write { padding-left: 8px; padding-right: 8px; }
body.typora-export { padding-left: 30px; padding-right: 30px; }
.typora-export .footnote-line, .typora-export li, .typora-export p { white-space: pre-wrap; }
.typora-export .task-list-item input { pointer-events: none; }
@media screen and (max-width: 500px) {
  body.typora-export { padding-left: 0px; padding-right: 0px; }
  #write { padding-left: 20px; padding-right: 20px; }
  .CodeMirror-sizer { margin-left: 0px !important; }
  .CodeMirror-gutters { display: none !important; }
}
#write li > figure:last-child { margin-bottom: 0.5rem; }
#write ol, #write ul { position: relative; }
img { max-width: 100%; vertical-align: middle; image-orientation: from-image; }
button, input, select, textarea { color: inherit; font: inherit; }
input[type="checkbox"], input[type="radio"] { line-height: normal; padding: 0px; }
*, ::after, ::before { box-sizing: border-box; }
#write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write p, #write pre { width: inherit; }
#write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write p { position: relative; }
p { line-height: inherit; }
h1, h2, h3, h4, h5, h6 { break-after: avoid-page; break-inside: avoid; orphans: 4; }
p { orphans: 4; }
h1 { font-size: 2rem; }
h2 { font-size: 1.8rem; }
h3 { font-size: 1.6rem; }
h4 { font-size: 1.4rem; }
h5 { font-size: 1.2rem; }
h6 { font-size: 1rem; }
.md-math-block, .md-rawblock, h1, h2, h3, h4, h5, h6, p { margin-top: 1rem; margin-bottom: 1rem; }
.hidden { display: none; }
.md-blockmeta { color: rgb(204, 204, 204); font-weight: 700; font-style: italic; }
a { cursor: pointer; }
sup.md-footnote { padding: 2px 4px; background-color: rgba(238, 238, 238, 0.7); color: rgb(85, 85, 85); border-radius: 4px; cursor: pointer; }
sup.md-footnote a, sup.md-footnote a:hover { color: inherit; text-transform: inherit; text-decoration: inherit; }
#write input[type="checkbox"] { cursor: pointer; width: inherit; height: inherit; }
figure { overflow-x: auto; margin: 1.2em 0px; max-width: calc(100% + 16px); padding: 0px; }
figure > table { margin: 0px; }
tr { break-inside: avoid; break-after: auto; }
thead { display: table-header-group; }
table { border-collapse: collapse; border-spacing: 0px; width: 100%; overflow: auto; break-inside: auto; text-align: left; }
table.md-table td { min-width: 32px; }
.CodeMirror-gutters { border-right: 0px; background-color: inherit; }
.CodeMirror-linenumber { user-select: none; }
.CodeMirror { text-align: left; }
.CodeMirror-placeholder { opacity: 0.3; }
.CodeMirror pre { padding: 0px 4px; }
.CodeMirror-lines { padding: 0px; }
div.hr:focus { cursor: none; }
#write pre { white-space: pre-wrap; }
#write.fences-no-line-wrapping pre { white-space: pre; }
#write pre.ty-contain-cm { white-space: normal; }
.CodeMirror-gutters { margin-right: 4px; }
.md-fences { font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; overflow: visible; white-space: pre; background: inherit; position: relative !important; }
.md-diagram-panel { width: 100%; margin-top: 10px; text-align: center; padding-top: 0px; padding-bottom: 8px; overflow-x: auto; }
#write .md-fences.mock-cm { white-space: pre-wrap; }
.md-fences.md-fences-with-lineno { padding-left: 0px; }
#write.fences-no-line-wrapping .md-fences.mock-cm { white-space: pre; overflow-x: auto; }
.md-fences.mock-cm.md-fences-with-lineno { padding-left: 8px; }
.CodeMirror-line, twitterwidget { break-inside: avoid; }
.footnotes { opacity: 0.8; font-size: 0.9rem; margin-top: 1em; margin-bottom: 1em; }
.footnotes + .footnotes { margin-top: 0px; }
.md-reset { margin: 0px; padding: 0px; border: 0px; outline: 0px; vertical-align: top; background: 0px 0px; text-decoration: none; text-shadow: none; float: none; position: static; width: auto; height: auto; white-space: nowrap; cursor: inherit; -webkit-tap-highlight-color: transparent; line-height: normal; font-weight: 400; text-align: left; box-sizing: content-box; direction: ltr; }
li div { padding-top: 0px; }
blockquote { margin: 1rem 0px; }
li .mathjax-block, li p { margin: 0.5rem 0px; }
li { margin: 0px; position: relative; }
blockquote > :last-child { margin-bottom: 0px; }
blockquote > :first-child, li > :first-child { margin-top: 0px; }
.footnotes-area { color: rgb(136, 136, 136); margin-top: 0.714rem; padding-bottom: 0.143rem; white-space: normal; }
#write .footnote-line { white-space: pre-wrap; }
@media print {
  body, html { border: 1px solid transparent; height: 99%; break-after: avoid; break-before: avoid; font-variant-ligatures: no-common-ligatures; }
  #write { margin-top: 0px; padding-top: 0px; border-color: transparent !important; }
  .typora-export * { -webkit-print-color-adjust: exact; }
  html.blink-to-pdf { font-size: 13px; }
  .typora-export #write { break-after: avoid; }
  .typora-export #write::after { height: 0px; }
  .is-mac table { break-inside: avoid; }
}
.footnote-line { margin-top: 0.714em; font-size: 0.7em; }
a img, img a { cursor: pointer; }
pre.md-meta-block { font-size: 0.8rem; min-height: 0.8rem; white-space: pre-wrap; background: rgb(204, 204, 204); display: block; overflow-x: hidden; }
p > .md-image:only-child:not(.md-img-error) img, p > img:only-child { display: block; margin: auto; }
#write.first-line-indent p > .md-image:only-child:not(.md-img-error) img { left: -2em; position: relative; }
p > .md-image:only-child { display: inline-block; width: 100%; }
#write .MathJax_Display { margin: 0.8em 0px 0px; }
.md-math-block { width: 100%; }
.md-math-block:not(:empty)::after { display: none; }
[contenteditable="true"]:active, [contenteditable="true"]:focus, [contenteditable="false"]:active, [contenteditable="false"]:focus { outline: 0px; box-shadow: none; }
.md-task-list-item { position: relative; list-style-type: none; }
.task-list-item.md-task-list-item { padding-left: 0px; }
.md-task-list-item > input { position: absolute; top: 0px; left: 0px; margin-left: -1.2em; margin-top: calc(1em - 10px); border: none; }
.math { font-size: 1rem; }
.md-toc { min-height: 3.58rem; position: relative; font-size: 0.9rem; border-radius: 10px; }
.md-toc-content { position: relative; margin-left: 0px; }
.md-toc-content::after, .md-toc::after { display: none; }
.md-toc-item { display: block; color: rgb(65, 131, 196); }
.md-toc-item a { text-decoration: none; }
.md-toc-inner:hover { text-decoration: underline; }
.md-toc-inner { display: inline-block; cursor: pointer; }
.md-toc-h1 .md-toc-inner { margin-left: 0px; font-weight: 700; }
.md-toc-h2 .md-toc-inner { margin-left: 2em; }
.md-toc-h3 .md-toc-inner { margin-left: 4em; }
.md-toc-h4 .md-toc-inner { margin-left: 6em; }
.md-toc-h5 .md-toc-inner { margin-left: 8em; }
.md-toc-h6 .md-toc-inner { margin-left: 10em; }
@media screen and (max-width: 48em) {
  .md-toc-h3 .md-toc-inner { margin-left: 3.5em; }
  .md-toc-h4 .md-toc-inner { margin-left: 5em; }
  .md-toc-h5 .md-toc-inner { margin-left: 6.5em; }
  .md-toc-h6 .md-toc-inner { margin-left: 8em; }
}
a.md-toc-inner { font-size: inherit; font-style: inherit; font-weight: inherit; line-height: inherit; }
.footnote-line a:not(.reversefootnote) { color: inherit; }
.md-attr { display: none; }
.md-fn-count::after { content: "."; }
code, pre, samp, tt { font-family: var(--monospace); }
kbd { margin: 0px 0.1em; padding: 0.1em 0.6em; font-size: 0.8em; color: rgb(36, 39, 41); background: rgb(255, 255, 255); border: 1px solid rgb(173, 179, 185); border-radius: 3px; box-shadow: rgba(12, 13, 14, 0.2) 0px 1px 0px, rgb(255, 255, 255) 0px 0px 0px 2px inset; white-space: nowrap; vertical-align: middle; }
.md-comment { color: rgb(162, 127, 3); opacity: 0.8; font-family: var(--monospace); }
code { text-align: left; vertical-align: initial; }
a.md-print-anchor { white-space: pre !important; border-width: initial !important; border-style: none !important; border-color: initial !important; display: inline-block !important; position: absolute !important; width: 1px !important; right: 0px !important; outline: 0px !important; background: 0px 0px !important; text-decoration: initial !important; text-shadow: initial !important; }
.md-inline-math .MathJax_SVG .noError { display: none !important; }
.html-for-mac .inline-math-svg .MathJax_SVG { vertical-align: 0.2px; }
.md-math-block .MathJax_SVG_Display { text-align: center; margin: 0px; position: relative; text-indent: 0px; max-width: none; max-height: none; min-height: 0px; min-width: 100%; width: auto; overflow-y: hidden; display: block !important; }
.MathJax_SVG_Display, .md-inline-math .MathJax_SVG_Display { width: auto; margin: inherit; display: inline-block !important; }
.MathJax_SVG .MJX-monospace { font-family: var(--monospace); }
.MathJax_SVG .MJX-sans-serif { font-family: sans-serif; }
.MathJax_SVG { display: inline; font-style: normal; font-weight: 400; line-height: normal; zoom: 90%; text-indent: 0px; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; overflow-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border: 0px; padding: 0px; margin: 0px; }
.MathJax_SVG * { transition: none 0s ease 0s; }
.MathJax_SVG_Display svg { vertical-align: middle !important; margin-bottom: 0px !important; margin-top: 0px !important; }
.os-windows.monocolor-emoji .md-emoji { font-family: "Segoe UI Symbol", sans-serif; }
.md-diagram-panel > svg { max-width: 100%; }
[lang="flow"] svg, [lang="mermaid"] svg { max-width: 100%; height: auto; }
[lang="mermaid"] .node text { font-size: 1rem; }
table tr th { border-bottom: 0px; }
video { max-width: 100%; display: block; margin: 0px auto; }
iframe { max-width: 100%; width: 100%; border: none; }
.highlight td, .highlight tr { border: 0px; }
svg[id^="mermaidChart"] { line-height: 1em; }
mark { background: rgb(255, 255, 0); color: rgb(0, 0, 0); }
.md-html-inline .md-plain, .md-html-inline strong, mark .md-inline-math, mark strong { color: inherit; }
mark .md-meta { color: rgb(0, 0, 0); opacity: 0.3 !important; }
@media print {
  .typora-export h1, .typora-export h2, .typora-export h3, .typora-export h4, .typora-export h5, .typora-export h6 { break-inside: avoid; }
}


.CodeMirror { height: auto; }
.CodeMirror.cm-s-inner { background: inherit; }
.CodeMirror-scroll { overflow: auto hidden; z-index: 3; }
.CodeMirror-gutter-filler, .CodeMirror-scrollbar-filler { background-color: rgb(255, 255, 255); }
.CodeMirror-gutters { border-right: 1px solid rgb(221, 221, 221); background: inherit; white-space: nowrap; }
.CodeMirror-linenumber { padding: 0px 3px 0px 5px; text-align: right; color: rgb(153, 153, 153); }
.cm-s-inner .cm-keyword { color: rgb(119, 0, 136); }
.cm-s-inner .cm-atom, .cm-s-inner.cm-atom { color: rgb(34, 17, 153); }
.cm-s-inner .cm-number { color: rgb(17, 102, 68); }
.cm-s-inner .cm-def { color: rgb(0, 0, 255); }
.cm-s-inner .cm-variable { color: rgb(0, 0, 0); }
.cm-s-inner .cm-variable-2 { color: rgb(0, 85, 170); }
.cm-s-inner .cm-variable-3 { color: rgb(0, 136, 85); }
.cm-s-inner .cm-string { color: rgb(170, 17, 17); }
.cm-s-inner .cm-property { color: rgb(0, 0, 0); }
.cm-s-inner .cm-operator { color: rgb(152, 26, 26); }
.cm-s-inner .cm-comment, .cm-s-inner.cm-comment { color: rgb(170, 85, 0); }
.cm-s-inner .cm-string-2 { color: rgb(255, 85, 0); }
.cm-s-inner .cm-meta { color: rgb(85, 85, 85); }
.cm-s-inner .cm-qualifier { color: rgb(85, 85, 85); }
.cm-s-inner .cm-builtin { color: rgb(51, 0, 170); }
.cm-s-inner .cm-bracket { color: rgb(153, 153, 119); }
.cm-s-inner .cm-tag { color: rgb(17, 119, 0); }
.cm-s-inner .cm-attribute { color: rgb(0, 0, 204); }
.cm-s-inner .cm-header, .cm-s-inner.cm-header { color: rgb(0, 0, 255); }
.cm-s-inner .cm-quote, .cm-s-inner.cm-quote { color: rgb(0, 153, 0); }
.cm-s-inner .cm-hr, .cm-s-inner.cm-hr { color: rgb(153, 153, 153); }
.cm-s-inner .cm-link, .cm-s-inner.cm-link { color: rgb(0, 0, 204); }
.cm-negative { color: rgb(221, 68, 68); }
.cm-positive { color: rgb(34, 153, 34); }
.cm-header, .cm-strong { font-weight: 700; }
.cm-del { text-decoration: line-through; }
.cm-em { font-style: italic; }
.cm-link { text-decoration: underline; }
.cm-error { color: red; }
.cm-invalidchar { color: red; }
.cm-constant { color: rgb(38, 139, 210); }
.cm-defined { color: rgb(181, 137, 0); }
div.CodeMirror span.CodeMirror-matchingbracket { color: rgb(0, 255, 0); }
div.CodeMirror span.CodeMirror-nonmatchingbracket { color: rgb(255, 34, 34); }
.cm-s-inner .CodeMirror-activeline-background { background: inherit; }
.CodeMirror { position: relative; overflow: hidden; }
.CodeMirror-scroll { height: 100%; outline: 0px; position: relative; box-sizing: content-box; background: inherit; }
.CodeMirror-sizer { position: relative; }
.CodeMirror-gutter-filler, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-vscrollbar { position: absolute; z-index: 6; display: none; }
.CodeMirror-vscrollbar { right: 0px; top: 0px; overflow: hidden; }
.CodeMirror-hscrollbar { bottom: 0px; left: 0px; overflow: hidden; }
.CodeMirror-scrollbar-filler { right: 0px; bottom: 0px; }
.CodeMirror-gutter-filler { left: 0px; bottom: 0px; }
.CodeMirror-gutters { position: absolute; left: 0px; top: 0px; padding-bottom: 30px; z-index: 3; }
.CodeMirror-gutter { white-space: normal; height: 100%; box-sizing: content-box; padding-bottom: 30px; margin-bottom: -32px; display: inline-block; }
.CodeMirror-gutter-wrapper { position: absolute; z-index: 4; background: 0px 0px !important; border: none !important; }
.CodeMirror-gutter-background { position: absolute; top: 0px; bottom: 0px; z-index: 4; }
.CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4; }
.CodeMirror-lines { cursor: text; }
.CodeMirror pre { border-radius: 0px; border-width: 0px; background: 0px 0px; font-family: inherit; font-size: inherit; margin: 0px; white-space: pre; overflow-wrap: normal; color: inherit; z-index: 2; position: relative; overflow: visible; }
.CodeMirror-wrap pre { overflow-wrap: break-word; white-space: pre-wrap; word-break: normal; }
.CodeMirror-code pre { border-right: 30px solid transparent; width: fit-content; }
.CodeMirror-wrap .CodeMirror-code pre { border-right: none; width: auto; }
.CodeMirror-linebackground { position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; z-index: 0; }
.CodeMirror-linewidget { position: relative; z-index: 2; overflow: auto; }
.CodeMirror-wrap .CodeMirror-scroll { overflow-x: hidden; }
.CodeMirror-measure { position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden; }
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor { position: absolute; visibility: hidden; border-right: none; width: 0px; }
.CodeMirror div.CodeMirror-cursor { visibility: hidden; }
.CodeMirror-focused div.CodeMirror-cursor { visibility: inherit; }
.cm-searching { background: rgba(255, 255, 0, 0.4); }
@media print {
  .CodeMirror div.CodeMirror-cursor { visibility: hidden; }
}


:root {
    --side-bar-bg-color: #fafafa;
    --control-text-color: #777;
}

@include-when-export url(https://fonts.loli.net/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext);

/* open-sans-regular - latin-ext_latin */
  /* open-sans-italic - latin-ext_latin */
    /* open-sans-700 - latin-ext_latin */
    /* open-sans-700italic - latin-ext_latin */
  html {
    font-size: 16px;
}

body {
    font-family: "Open Sans","Clear Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
    color: rgb(51, 51, 51);
    line-height: 1.6;
}

#write {
    max-width: 860px;
  	margin: 0 auto;
  	padding: 30px;
    padding-bottom: 100px;
}

@media only screen and (min-width: 1400px) {
	#write {
		max-width: 1024px;
	}
}

@media only screen and (min-width: 1800px) {
	#write {
		max-width: 1200px;
	}
}

#write > ul:first-child,
#write > ol:first-child{
    margin-top: 30px;
}

a {
    color: #4183C4;
}
h1,
h2,
h3,
h4,
h5,
h6 {
    position: relative;
    margin-top: 1rem;
    margin-bottom: 1rem;
    font-weight: bold;
    line-height: 1.4;
    cursor: text;
}
h1:hover a.anchor,
h2:hover a.anchor,
h3:hover a.anchor,
h4:hover a.anchor,
h5:hover a.anchor,
h6:hover a.anchor {
    text-decoration: none;
}
h1 tt,
h1 code {
    font-size: inherit;
}
h2 tt,
h2 code {
    font-size: inherit;
}
h3 tt,
h3 code {
    font-size: inherit;
}
h4 tt,
h4 code {
    font-size: inherit;
}
h5 tt,
h5 code {
    font-size: inherit;
}
h6 tt,
h6 code {
    font-size: inherit;
}
h1 {
    font-size: 2.25em;
    line-height: 1.2;
    border-bottom: 1px solid #eee;
}
h2 {
    font-size: 1.75em;
    line-height: 1.225;
    border-bottom: 1px solid #eee;
}

/*@media print {
    .typora-export h1,
    .typora-export h2 {
        border-bottom: none;
        padding-bottom: initial;
    }

    .typora-export h1::after,
    .typora-export h2::after {
        content: "";
        display: block;
        height: 100px;
        margin-top: -96px;
        border-top: 1px solid #eee;
    }
}*/

h3 {
    font-size: 1.5em;
    line-height: 1.43;
}
h4 {
    font-size: 1.25em;
}
h5 {
    font-size: 1em;
}
h6 {
   font-size: 1em;
    color: #777;
}
p,
blockquote,
ul,
ol,
dl,
table{
    margin: 0.8em 0;
}
li>ol,
li>ul {
    margin: 0 0;
}
hr {
    height: 2px;
    padding: 0;
    margin: 16px 0;
    background-color: #e7e7e7;
    border: 0 none;
    overflow: hidden;
    box-sizing: content-box;
}

li p.first {
    display: inline-block;
}
ul,
ol {
    padding-left: 30px;
}
ul:first-child,
ol:first-child {
    margin-top: 0;
}
ul:last-child,
ol:last-child {
    margin-bottom: 0;
}
blockquote {
    border-left: 4px solid #dfe2e5;
    padding: 0 15px;
    color: #777777;
}
blockquote blockquote {
    padding-right: 0;
}
table {
    padding: 0;
    word-break: initial;
}
table tr {
    border-top: 1px solid #dfe2e5;
    margin: 0;
    padding: 0;
}
table tr:nth-child(2n),
thead {
    background-color: #f8f8f8;
}
table tr th {
    font-weight: bold;
    border: 1px solid #dfe2e5;
    border-bottom: 0;
    margin: 0;
    padding: 6px 13px;
}
table tr td {
    border: 1px solid #dfe2e5;
    margin: 0;
    padding: 6px 13px;
}
table tr th:first-child,
table tr td:first-child {
    margin-top: 0;
}
table tr th:last-child,
table tr td:last-child {
    margin-bottom: 0;
}

.CodeMirror-lines {
    padding-left: 4px;
}

.code-tooltip {
    box-shadow: 0 1px 1px 0 rgba(0,28,36,.3);
    border-top: 1px solid #eef2f2;
}

.md-fences,
code,
tt {
    border: 1px solid #e7eaed;
    background-color: #f8f8f8;
    border-radius: 3px;
    padding: 0;
    padding: 2px 4px 0px 4px;
    font-size: 0.9em;
}

code {
    background-color: #f3f4f4;
    padding: 0 2px 0 2px;
}

.md-fences {
    margin-bottom: 15px;
    margin-top: 15px;
    padding-top: 8px;
    padding-bottom: 6px;
}


.md-task-list-item > input {
  margin-left: -1.3em;
}

@media print {
    html {
        font-size: 13px;
    }
    table,
    pre {
        page-break-inside: avoid;
    }
    pre {
        word-wrap: break-word;
    }
}

.md-fences {
	background-color: #f8f8f8;
}
#write pre.md-meta-block {
	padding: 1rem;
    font-size: 85%;
    line-height: 1.45;
    background-color: #f7f7f7;
    border: 0;
    border-radius: 3px;
    color: #777777;
    margin-top: 0 !important;
}

.mathjax-block>.code-tooltip {
	bottom: .375rem;
}

.md-mathjax-midline {
    background: #fafafa;
}

#write>h3.md-focus:before{
	left: -1.5625rem;
	top: .375rem;
}
#write>h4.md-focus:before{
	left: -1.5625rem;
	top: .285714286rem;
}
#write>h5.md-focus:before{
	left: -1.5625rem;
	top: .285714286rem;
}
#write>h6.md-focus:before{
	left: -1.5625rem;
	top: .285714286rem;
}
.md-image>.md-meta {
    /*border: 1px solid #ddd;*/
    border-radius: 3px;
    padding: 2px 0px 0px 4px;
    font-size: 0.9em;
    color: inherit;
}

.md-tag {
    color: #a7a7a7;
    opacity: 1;
}

.md-toc { 
    margin-top:20px;
    padding-bottom:20px;
}

.sidebar-tabs {
    border-bottom: none;
}

#typora-quick-open {
    border: 1px solid #ddd;
    background-color: #f8f8f8;
}

#typora-quick-open-item {
    background-color: #FAFAFA;
    border-color: #FEFEFE #e5e5e5 #e5e5e5 #eee;
    border-style: solid;
    border-width: 1px;
}

/** focus mode */
.on-focus-mode blockquote {
    border-left-color: rgba(85, 85, 85, 0.12);
}

header, .context-menu, .megamenu-content, footer{
    font-family: "Segoe UI", "Arial", sans-serif;
}

.file-node-content:hover .file-node-icon,
.file-node-content:hover .file-node-open-state{
    visibility: visible;
}

.mac-seamless-mode #typora-sidebar {
    background-color: #fafafa;
    background-color: var(--side-bar-bg-color);
}

.md-lang {
    color: #b4654d;
}

.html-for-mac .context-menu {
    --item-hover-bg-color: #E6F0FE;
}

#md-notification .btn {
    border: 0;
}

.dropdown-menu .divider {
    border-color: #e5e5e5;
}

.ty-preferences .window-content {
    background-color: #fafafa;
}

.ty-preferences .nav-group-item.active {
    color: white;
    background: #999;
}


</style>
</head>
<body class='typora-export os-windows'>
<div id='write'  class=''><h2><a name="一系统移植" class="md-header-anchor"></a><span>一、系统移植</span></h2><p><span>在开发前，需要做uboot、linux内核、根文件系统的移植。移植完成后，再在这个基础上进行开发。</span></p><h3><a name="常用命令" class="md-header-anchor"></a><span>常用命令</span></h3><ul><li><span>xxd命令</span></li></ul><p><span>可以使用 </span><code>xxd</code><span> 命令的 </span><code>-g</code><span> 选项来指定显示的字节数量，以及 </span><code>-c</code><span> 选项来指定每行显示的字节数，</span><code>-l</code><span> 选项来指定需要显示的字节数量，以及 </span><code>-s</code><span> 选项来指定需要跳过的字节数量。</span></p><p><span>例如：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">xxd -g 1 -c 16 -s 0 -l 320 zImage</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">就是输出320个字节的内容</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 46px;"></div><div class="CodeMirror-gutters" style="display: none; height: 46px;"></div></div></div></pre><p>&nbsp;</p><ul><li><span>du命令</span></li></ul><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">du -b zImage </span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">可以查看zImage的字节数</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 46px;"></div><div class="CodeMirror-gutters" style="display: none; height: 46px;"></div></div></div></pre><p>&nbsp;</p><p>&nbsp;</p><h3><a name="11-u-boot移植" class="md-header-anchor"></a><span>1.1 u-boot移植</span></h3><p><span>一般是在半导体厂商给出的uboot的基础上，针对自己的把板子进行移植。</span></p><p><span>以正点原子的阿尔法开发板为例，在NXP官方给出的uboot的基础上，添加新的板子，步骤如下：</span></p><h4><a name="111-添加开发板默认配置文件" class="md-header-anchor"></a><span>1.1.1 添加开发板默认配置文件</span></h4><p><span>切到configs目录下，复制 mx6ull_14x14_evk_emmc_defconfig，然后重命名为 mx6ull_alientek_emmc_defconfig，命令如下：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre>x</pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">cd configs</span></pre></div><div class="" style="position: relative;"><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">cp mx6ull_14x14_evk_emmc_defconfig mx6ull_alientek_emmc_defconfig</span></pre></div></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 46px;"></div><div class="CodeMirror-gutters" style="display: none; height: 46px;"></div></div></div></pre><p>&nbsp;</p><p><span>然后，将新的defconfig修改如下：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ull_alientek_</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">emmc/imximage.cfg,MX6ULL_EVK_EMMC_REWORK"</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">CONFIG_ARM=y</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">CONFIG_ARCH_MX6=y</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">CONFIG_TARGET_MX6ULL_ALIENTEK_EMMC=y</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">CONFIG_CMD_GPIO=y</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 138px;"></div><div class="CodeMirror-gutters" style="display: none; height: 138px;"></div></div></div></pre><p><span>修改了第1行和第4行。</span></p><p>&nbsp;</p><h4><a name="112-添加开发板对应的头文件" class="md-header-anchor"></a><span>1.1.2 添加开发板对应的头文件</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181901333.png" referrerpolicy="no-referrer" alt="image-20230618190105264"></p><p>&nbsp;</p><h4><a name="113-添加开发板对应的板级文件夹" class="md-header-anchor"></a><span>1.1.3 添加开发板对应的板级文件夹</span></h4><p><span>在board/freescale文件夹下，存放着板子对应的文件夹</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181902135.png" referrerpolicy="no-referrer" alt="image-20230618190247095"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181903572.png" referrerpolicy="no-referrer" alt="image-20230618190303536"></p><p><span>之后，要对该目录下的Makefile、imximage.cfg、Kconfig、MAINTAINERS文件进行修改。</span></p><h5><a name="1）修改makefile文件" class="md-header-anchor"></a><span>1）修改Makefile文件</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181913681.png" referrerpolicy="no-referrer" alt="image-20230618191339628"></p><p>&nbsp;</p><h5><a name="2）修改imximagecfg文件" class="md-header-anchor"></a><span>2）修改imximage.cfg文件</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181908103.png" referrerpolicy="no-referrer" alt="image-20230618190802066"></p><p>&nbsp;</p><h5><a name="3）修改kconfig文件" class="md-header-anchor"></a><span>3）修改Kconfig文件</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181908695.png" referrerpolicy="no-referrer" alt="image-20230618190852653"></p><h5><a name="4）修改maintainers文件" class="md-header-anchor"></a><span>4）修改MAINTAINERS文件</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181909814.png" referrerpolicy="no-referrer" alt="image-20230618190936772"></p><p>&nbsp;</p><h4><a name="114-修改uboot的图形界面配置文件" class="md-header-anchor"></a><span>1.1.4 修改uboot的图形界面配置文件</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181913397.png" referrerpolicy="no-referrer" alt="image-20230618191307336"></p><p>&nbsp;</p><h4><a name="115-编译修改后的板子的uboot" class="md-header-anchor"></a><span>1.1.5 编译修改后的板子的uboot</span></h4><p><span>新建一个脚本mx6ull_alientek_emmc.sh，内容如下：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">#!/bin/bash</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_alientek_emmc_defconfig</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 92px;"></div><div class="CodeMirror-gutters" style="display: none; height: 92px;"></div></div></div></pre><p>&nbsp;</p><h4><a name="116-烧录" class="md-header-anchor"></a><span>1.1.6 烧录</span></h4><p><span>使用提供的烧录工具，将编译完成后的u-boot.bin烧录至SD卡中，然后将开发板的BOOT CFG调到SD卡启动，插入SD卡，即可完成启动。</span></p><p>&nbsp;</p><h4><a name="117-修改led驱动" class="md-header-anchor"></a><span>1.1.7 修改LED驱动</span></h4><p><span>在uboot启动的时候，可以显示NXP的logo，需要在mx6ull_alientek_emmc.c中，找到以下内容：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181928364.png" referrerpolicy="no-referrer" alt="image-20230618192840313"></p><p>&nbsp;</p><p><span>修改成：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="C" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-operator">/</span><span class="cm-variable">LCD屏幕参数设置</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">struct</span> <span class="cm-def">display_info_t</span> <span class="cm-keyword">const</span> <span class="cm-variable">displays</span>[] <span class="cm-operator">=</span> {{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">bus</span> <span class="cm-operator">=</span> <span class="cm-variable">MX6UL_LCDIF1_BASE_ADDR</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">addr</span> <span class="cm-operator">=</span> <span class="cm-number">0</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">pixfmt</span> <span class="cm-operator">=</span> <span class="cm-number">24</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">detect</span> <span class="cm-operator">=</span> <span class="cm-variable">NULL</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">enable</span><span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-operator">=</span> <span class="cm-variable">do_enable_parallel_lcd</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">mode</span><span class="cm-tab" role="presentation" cm-text="	">   </span><span class="cm-operator">=</span> {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">name</span><span class="cm-tab" role="presentation" cm-text="	">   </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-operator">=</span> <span class="cm-string">"TFT7084"</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">xres</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-operator">=</span> <span class="cm-number">800</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">yres</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-operator">=</span> <span class="cm-number">480</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">pixclock</span> &nbsp; &nbsp; &nbsp; <span class="cm-operator">=</span> <span class="cm-number">30000</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">left_margin</span> &nbsp; &nbsp;<span class="cm-operator">=</span> <span class="cm-number">46</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">right_margin</span> &nbsp; <span class="cm-operator">=</span> <span class="cm-number">210</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">upper_margin</span> &nbsp; <span class="cm-operator">=</span> <span class="cm-number">23</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">lower_margin</span> &nbsp; <span class="cm-operator">=</span> <span class="cm-number">22</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">hsync_len</span> &nbsp; &nbsp; &nbsp;<span class="cm-operator">=</span> <span class="cm-number">1</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">vsync_len</span> &nbsp; &nbsp; &nbsp;<span class="cm-operator">=</span> <span class="cm-number">1</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">sync</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-operator">=</span> <span class="cm-number">0</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">vmode</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-operator">=</span> <span class="cm-variable">FB_VMODE_NONINTERLACED</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">} } };</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 483px;"></div><div class="CodeMirror-gutters" style="display: none; height: 483px;"></div></div></div></pre><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181930803.png" referrerpolicy="no-referrer" alt="image-20230618193053763"></p><p><span>因为环境变量有保存到EMMC中，uboot启动会从emmc中读取环境变量的值，如果环境变量中没值才会用mx6ull_alientek_emmc.h中的默认环境变量。则：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">setenv panel TFT7084</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">saveenv</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 46px;"></div><div class="CodeMirror-gutters" style="display: none; height: 46px;"></div></div></div></pre><p><span>设置完成后重启，就能看到屏幕正常显示了，确实是800x480的TFT7084。</span></p><p>&nbsp;</p><h4><a name="118-修改网络驱动" class="md-header-anchor"></a><span>1.1.8 修改网络驱动</span></h4><h5><a name="1）原理" class="md-header-anchor"></a><span>1）原理</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181936092.png" referrerpolicy="no-referrer" alt="image-20230618193602049"></p><p><span>要修改ENET1和ENET2的网络驱动，重要的是修改以下三点：</span></p><p><span>ENET1/2 复位引脚，SR8201F 的器件 ID，SR8201F 驱动。</span></p><p>&nbsp;</p><h5><a name="2）网络phy地址修改" class="md-header-anchor"></a><span>2）网络PHY地址修改</span></h5><p><span>首先修改 uboot 中的 ENET1 和 ENET2 的 PHY 地址和驱动，打开 mx6ull_alientek_emmc.h修改</span></p><p><span>正点原子的 I.MX6U-ALPHA 开发板 ENET1 的 PHY 地址刚好也为 0X2，ENET2 的 PHY 地址也是 0X1，所以可以直接使用默认配置，不需要我们修改。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181944307.png" referrerpolicy="no-referrer" alt="image-20230618194421264"></p><p><span>修改最后一行，在#endif前添加一句，使能REALTEK公司的PHY驱动：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">#define CONFIG_PHYLIB</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">#define CONFIG_PHY_REALTEK --这句是要加的</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">#endif</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">原本在该位置的 #define CONFIG_PHY_MICREL 要删除</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 115px;"></div><div class="CodeMirror-gutters" style="display: none; height: 115px;"></div></div></div></pre><p>&nbsp;</p><h5><a name="3）删除-uboot-中-74lv595-的驱动代码" class="md-header-anchor"></a><span>3）</span><strong><span>删除</span></strong><span> </span><strong><span>uboot</span></strong><span> </span><strong><span>中</span></strong><span> </span><strong><span>74LV595</span></strong><span> 的驱动代码</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181950073.png" referrerpolicy="no-referrer" alt="image-20230618195007025"></p><p><span>修改完这里后，要删除74LV595的驱动代码。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181951207.png" referrerpolicy="no-referrer" alt="image-20230618195159161"></p><p>&nbsp;</p><p><strong><span>iox74lv_init</span></strong><span> 和 </span><strong><span>iox74lv_set</span></strong><span> 这两个函数也要全部删除。</span></p><p><span>board_init函数中的两行也要删除：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306181953464.png" referrerpolicy="no-referrer" alt="image-20230618195303424"></p><p>&nbsp;</p><h5><a name="4）添加开发板网络驱动复位引脚代码" class="md-header-anchor"></a><span>4）添加开发板网络驱动复位引脚代码</span></h5><p><span>首先，在两个网络IO结构体数组中，添加两个网口的复位IO配置参数（其实就是</span><strong><span>在最后加了一句话</span></strong><span>）</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">static iomux_v3_cfg_t const fec1_pads[] = {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>MX6_PAD_GPIO1_IO06__ENET1_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>......</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">static iomux_v3_cfg_t const fec2_pads[] = {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>MX6_PAD_GPIO1_IO06__ENET2_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL),</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>......</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 253px;"></div><div class="CodeMirror-gutters" style="display: none; height: 253px;"></div></div></div></pre><p><span>然后，找到</span><strong><span>setup_iomux_fec</span></strong><span>这个函数，这个函数是根据fec1_pads和fec2_pads这两个网络IO配置数组来初始化网络IO的。</span></p><p><span>整个替换，修改后的这个函数如下：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">static void setup_iomux_fec(int fec_id)</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>if (fec_id == 0)</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>imx_iomux_v3_setup_multiple_pads(fec1_pads,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span> ARRAY_SIZE(fec1_pads));</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>gpio_direction_output(ENET1_RESET, 1);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>gpio_set_value(ENET1_RESET, 0);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>mdelay(20);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>gpio_set_value(ENET1_RESET, 1);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>else</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>imx_iomux_v3_setup_multiple_pads(fec2_pads,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span> ARRAY_SIZE(fec2_pads));</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>gpio_direction_output(ENET2_RESET, 1);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>gpio_set_value(ENET2_RESET, 0);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>mdelay(20);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>gpio_set_value(ENET2_RESET, 1);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>mdelay(150);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 529px;"></div><div class="CodeMirror-gutters" style="display: none; height: 529px;"></div></div></div></pre><p><span>至此，已经修改完成。</span></p><p>&nbsp;</p><h3><a name="12-linux内核移植" class="md-header-anchor"></a><span>1.2 Linux内核移植</span></h3><p><span>uboot要启动linux内核。具体的启动流程，在之前的学习笔记中有写，这里主要是记录一下移植linux内核的移植。</span></p><h4><a name="121-添加开发板默认配置文件" class="md-header-anchor"></a><span>1.2.1 添加开发板默认配置文件</span></h4><p><span>配置开发板对应的defconfig文件。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306192108907.png" referrerpolicy="no-referrer" alt="image-20230619210806827"></p><p><span>改成下面这样：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306192109376.png" referrerpolicy="no-referrer" alt="image-20230619210908338"></p><p>&nbsp;</p><h4><a name="122-添加开发板默认配置文件" class="md-header-anchor"></a><span>1.2.2 添加开发板默认配置文件</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306192112092.png" referrerpolicy="no-referrer" alt="image-20230619211242044"></p><p>&nbsp;</p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306192113974.png" referrerpolicy="no-referrer" alt="image-20230619211350935"></p><p>&nbsp;</p><h4><a name="123-编译测试" class="md-header-anchor"></a><span>1.2.3 编译测试</span></h4><p><span>编译的步骤大概为：distclean清理一下（这步不一定需要），用defconfig文件配置，打开menuconfig（暂时没用到，按两下ESC），最后make。</span></p><p><span>脚本imx6ull_alientek_emmc.sh：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> #!/bin/sh</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j4</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 138px;"></div><div class="CodeMirror-gutters" style="display: none; height: 138px;"></div></div></div></pre><p>&nbsp;</p><h4><a name="124-修改cpu主频" class="md-header-anchor"></a><span>1.2.4 修改CPU主频</span></h4><p><span>进入到目录/sys/bus/cpu/devices/cpu0/cpufreq 中，可以查看频率相关的各种信息。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306192126677.png" referrerpolicy="no-referrer" alt="image-20230619212626613"></p><p><span>配置 Linux 内核，将调频策略选择为 performance。或者修改 imx_alientek_emmc_defconfig 文件，这与正点原子教程的其实不太一样，已经配置好了，不用自己做什么修改：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306192127117.png" referrerpolicy="no-referrer" alt="image-20230619212747068"></p><p>&nbsp;</p><h4><a name="125-修改网络驱动" class="md-header-anchor"></a><span>1.2.5 修改网络驱动</span></h4><h5><a name="1）修改sr8201f的复位以及网络时钟引脚驱动" class="md-header-anchor"></a><span>1）修改SR8201F的复位以及网络时钟引脚驱动</span></h5><p><span>删除高亮的部分：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306192130085.png" referrerpolicy="no-referrer" alt="image-20230619213004023"></p><p><span>然后找到名为</span><strong><span>iomuxc_snvs</span></strong><span>的节点，添加复位引脚信息。主要是ENET1和ENET2的网络复位引脚配置信息。</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-operator">&amp;</span><span class="cm-variable">iomuxc_snvs</span> {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">pinctrl</span><span class="cm-operator">-</span><span class="cm-variable">names</span> <span class="cm-operator">=</span> <span class="cm-string">"default_snvs"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-variable">pinctrl</span><span class="cm-operator">-</span><span class="cm-number">0</span> <span class="cm-operator">=</span> <span class="cm-operator">&lt;&amp;</span><span class="cm-variable">pinctrl_hog_2</span><span class="cm-operator">&gt;</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-variable">imx6ul</span><span class="cm-operator">-</span><span class="cm-variable">evk</span> {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">pinctrl_hog_2</span>: ......</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">//这下面是新加的</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">pinctrl_enet1_reset</span>: <span class="cm-variable">enet1resetgrp</span> {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">fsl</span>,<span class="cm-variable">pins</span> <span class="cm-operator">=</span> <span class="cm-operator">&lt;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* used for enet1 reset */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07</span> <span class="cm-number">0x10B0</span> </span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-operator">&gt;</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/*enet2 reset zuozhongkai*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">pinctrl_enet2_reset</span>: <span class="cm-variable">enet2resetgrp</span> {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">fsl</span>,<span class="cm-variable">pins</span> <span class="cm-operator">=</span> <span class="cm-operator">&lt;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* used for enet2 reset */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08</span> <span class="cm-number">0x10B0</span> </span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-operator">&gt;</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  };</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 529px;"></div><div class="CodeMirror-gutters" style="display: none; height: 529px;"></div></div></div></pre><p><span>最后还需要修改一下 ENET1 和 ENET2 的</span><strong><span>网络时钟引脚配置</span></strong><span>，继续在 imx6ull-alientekemmc.dts 中找到如下所示代码：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">pinctrl_enet1: enet1grp {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">fsl,pins = &lt;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  ......</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1<span class="cm-tab" role="presentation" cm-text="	">  </span>0x4001b031</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">  &gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">pinctrl_enet2: enet2grp {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">fsl,pins = &lt;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  ......</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2<span class="cm-tab" role="presentation" cm-text="	">  </span>0x4001b031</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">  &gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 299px;"></div><div class="CodeMirror-gutters" style="display: none; height: 299px;"></div></div></div></pre><p><span>主要是最后一行，原来默认值就是 0x4001b031，所以不需要改。</span></p><p>&nbsp;</p><h5><a name="2）修改-fec1和-fec2-节点的pinctrl-0-属性" class="md-header-anchor"></a><span>2）修改 fec1</span><strong><span>和</span></strong><span> fec2 节点的pinctrl-0 属性</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306192139463.png" referrerpolicy="no-referrer" alt="image-20230619213924404"></p><p>&nbsp;</p><h5><a name="3）修改sr8201f的phy地址" class="md-header-anchor"></a><span>3）修改SR8201F的PHY地址</span></h5><p><span>修改后的部分为：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">&amp;fec1 {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>pinctrl-names = "default";</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>pinctrl-0 = &lt;&amp;pinctrl_enet1</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>&amp;pinctrl_enet1_reset&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>phy-mode = "rmii";</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>phy-handle = &lt;&amp;ethphy0&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>phy-reset-gpios = &lt;&amp;gpio5 7 GPIO_ACTIVE_LOW&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>phy-reset-duration = &lt;200&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>status = "okay";</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">&amp;fec2 {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>pinctrl-names = "default";</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>pinctrl-0 = &lt;&amp;pinctrl_enet2</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>&amp;pinctrl_enet2_reset&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>phy-mode = "rmii";</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>phy-handle = &lt;&amp;ethphy1&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>phy-reset-gpios = &lt;&amp;gpio5 8 GPIO_ACTIVE_LOW&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>phy-reset-duration = &lt;200&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>status = "okay";</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>mdio {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>#address-cells = &lt;1&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>#size-cells = &lt;0&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>ethphy0: ethernet-phy@2 {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>compatible = "ethernet-phy-ieee802.3-c22";</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>smsc,disable-energy-detect;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>reg = &lt;2&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>ethphy1: ethernet-phy@1 {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>compatible = "ethernet-phy-ieee802.3-c22";</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>smsc,disable-energy-detect;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>reg = &lt;1&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 874px;"></div><div class="CodeMirror-gutters" style="display: none; height: 874px;"></div></div></div></pre><p><span>解析：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306192144554.png" referrerpolicy="no-referrer" alt="image-20230619214426499"></p><p>&nbsp;</p><h5><a name="4）修改fecmainc文件" class="md-header-anchor"></a><span>4）修改fec_main.c文件</span></h5><p><span>在</span><strong><span>fec_reset_phy</span></strong><span>函数的最后一行加上</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">msleep(200);</span></pre></div></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 23px;"></div><div class="CodeMirror-gutters" style="display: none; height: 23px;"></div></div></div></pre><p><span>根据 SR8201F 收据手册上的要求，SR8201F 在复位结束以后需要等待至少 150ms 才能操作 SR8201F，因此这里添加了一个 200ms 的延时。</span></p><p>&nbsp;</p><h4><a name="126-启动" class="md-header-anchor"></a><span>1.2.6 启动</span></h4><p><span>还没移植根文件系统，先使用emmc中正点原子放置的根文件系统。还是将zImage和dtb文件先加载到DRAM中，再使用bootz命令启动。</span></p><p>&nbsp;</p><h3><a name="13-构建根文件系统" class="md-header-anchor"></a><span>1.3 构建根文件系统</span></h3><h4><a name="131-通过busybox构建根文件系统" class="md-header-anchor"></a><span>1.3.1 通过busybox构建根文件系统</span></h4><p><span>首先，修改顶层Makefile</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306192212554.png" referrerpolicy="no-referrer" alt="image-20230619221203507"></p><p><span>然后，修改文件使得支持中文字符。</span></p><p><span>然后，配置一下。一般可以用make defconfig来使用默认配置，当然也可以用make menuconfig来进行可视化配置。具体步骤，见正点原子教程。</span></p><p><span>配置完成后，进行编译。CONFIG_PREFIX指定了编译结果放置的位置。</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">make install CONFIG_PREFIX=/home/ydwu/linux/rootfs</span></pre></div></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 23px;"></div><div class="CodeMirror-gutters" style="display: none; height: 23px;"></div></div></div></pre><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306192214390.png" referrerpolicy="no-referrer" alt="image-20230619221459334"></p><p>&nbsp;</p><h4><a name="132-向根文件系统添加lib库" class="md-header-anchor"></a><span>1.3.2 向根文件系统添加lib库</span></h4><h5><a name="1）向rootfslib-添加文件" class="md-header-anchor"></a><span>1）向rootfs/lib 添加文件</span></h5><p><span>首先，在rootfs下创建一个lib文件夹。</span></p><p><span>然后，切换到/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib 这个文件夹下，</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200100450.png" referrerpolicy="no-referrer" alt="image-20230620010052354"></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">cp *so* *.a /home/ydwu/linux/nfs/rootfs/lib/ -d</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">对于比较特殊的ld-linux-armhf.so.3这个文件，需要删除重新拉一次，不带-d参数：</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">cp  ld-linux-armhf.so.3 /home/ydwu/linux/nfs/rootfs/lib/</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">继续进入.../arm-linux-gnueabihf/lib这个文件夹中：</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">cp *so* *.a /home/zuozhongkai/linux/nfs/rootfs/lib/ -d</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 161px;"></div><div class="CodeMirror-gutters" style="display: none; height: 161px;"></div></div></div></pre><p>&nbsp;</p><h5><a name="2）向rootfsusrlib添加文件" class="md-header-anchor"></a><span>2）向rootfs/usr/lib添加文件</span></h5><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">将  /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">全部内容拷贝过去：</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">cp *so* *.a /home/zuozhongkai/linux/nfs/rootfs/usr/lib/ -d</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 92px;"></div><div class="CodeMirror-gutters" style="display: none; height: 92px;"></div></div></div></pre><p>&nbsp;</p><p><span>至此，已经添加完成。</span></p><p>&nbsp;</p><h4><a name="133-添加其它文件夹" class="md-header-anchor"></a><span>1.3.3 添加其它文件夹</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200107161.png" referrerpolicy="no-referrer" alt="image-20230620010759069"></p><p>&nbsp;</p><p>&nbsp;</p><h4><a name="134-完善根文件系统" class="md-header-anchor"></a><span>1.3.4 完善根文件系统</span></h4><h5><a name="1）创建etcinitdrcs文件" class="md-header-anchor"></a><span>1）创建/etc/init.d/rcS文件</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200109878.png" referrerpolicy="no-referrer" alt="image-20230620010923818"></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">#!/bin/sh</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">export PATH LD_LIBRARY_PATH</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> </span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">mount -a</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">mkdir /dev/pts</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">mount -t devpts devpts /dev/pts</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">echo /sbin/mdev &gt; /proc/sys/kernel/hotplug</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">mdev -s</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 276px;"></div><div class="CodeMirror-gutters" style="display: none; height: 276px;"></div></div></div></pre><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200110617.png" referrerpolicy="no-referrer" alt="image-20230620011038530"></p><p>&nbsp;</p><p>&nbsp;</p><h5><a name="2）创建etcfstab文件" class="md-header-anchor"></a><span>2）创建/etc/fstab文件</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200111781.png" referrerpolicy="no-referrer" alt="image-20230620011114698"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200111566.png" referrerpolicy="no-referrer" alt="image-20230620011134496"></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">#&lt;file system&gt; &lt;mount point&gt; &lt;type&gt; &lt;options&gt; &lt;dump&gt; &lt;pass&gt;</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">proc /proc proc defaults 0 0</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">tmpfs /tmp tmpfs defaults 0 0</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">sysfs /sys sysfs defaults 0 0</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 92px;"></div><div class="CodeMirror-gutters" style="display: none; height: 92px;"></div></div></div></pre><p>&nbsp;</p><h5><a name="3）创建etcinittab文件" class="md-header-anchor"></a><span>3）创建/etc/inittab文件</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200113924.png" referrerpolicy="no-referrer" alt="image-20230620011359816"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200114486.png" referrerpolicy="no-referrer" alt="image-20230620011437376"></p><p>&nbsp;</p><h4><a name="135-测试" class="md-header-anchor"></a><span>1.3.5 测试</span></h4><h5><a name="1）软件运行测试" class="md-header-anchor"></a><span>1）软件运行测试</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200116004.png" referrerpolicy="no-referrer" alt="image-20230620011609912"></p><p><span>./hello可以执行，改成./hello &amp;则是可以在后台执行。</span></p><p><span>ps查看进程的pid，kill -9 64(64是要关的进程号) 即可关闭进程。</span></p><h5><a name="2）中文字符测试" class="md-header-anchor"></a><span>2）中文字符测试</span></h5><p><span>见教程文档。就是在session-&gt;terminal setting那里，把编码格式改成中文，然后测试：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200951318.png" referrerpolicy="no-referrer" alt="image-20230620095106257"></p><p><span>不过尽量还是用全英文开发，中文就图一乐子。</span></p><p>&nbsp;</p><h5><a name="3）开机自启动测试" class="md-header-anchor"></a><span>3）开机自启动测试</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200117838.png" referrerpolicy="no-referrer" alt="image-20230620011708765"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200117775.png" referrerpolicy="no-referrer" alt="image-20230620011726656"></p><p><span>修改后的rcS文件的内容：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="python" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="python"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">#!/bin/sh</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> </span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">PATH</span>=<span class="cm-operator">/</span><span class="cm-variable">sbin</span>:<span class="cm-operator">/</span><span class="cm-builtin">bin</span>:<span class="cm-operator">/</span><span class="cm-variable">usr</span><span class="cm-operator">/</span><span class="cm-variable">sbin</span>:<span class="cm-operator">/</span><span class="cm-variable">usr</span><span class="cm-operator">/</span><span class="cm-builtin">bin</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">LD_LIBRARY_PATH</span>=<span class="cm-error">$</span><span class="cm-variable">LD_LIBRARY_PATH</span>:<span class="cm-operator">/</span><span class="cm-variable">lib</span>:<span class="cm-operator">/</span><span class="cm-variable">usr</span><span class="cm-operator">/</span><span class="cm-variable">lib</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">runlevel</span>=<span class="cm-variable">S</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">umask</span> <span class="cm-error">0</span><span class="cm-number">22</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">export</span> <span class="cm-variable">PATH</span> <span class="cm-variable">LD_LIBRARY_PATH</span> <span class="cm-variable">runlevel</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">mount</span> <span class="cm-operator">-</span><span class="cm-variable">a</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">mkdir</span> <span class="cm-operator">/</span><span class="cm-variable">dev</span><span class="cm-operator">/</span><span class="cm-variable">pts</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">mount</span> <span class="cm-operator">-</span><span class="cm-variable">t</span> <span class="cm-variable">devpts</span> <span class="cm-variable">devpts</span> <span class="cm-operator">/</span><span class="cm-variable">dev</span><span class="cm-operator">/</span><span class="cm-variable">pts</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">echo</span> <span class="cm-operator">/</span><span class="cm-variable">sbin</span><span class="cm-operator">/</span><span class="cm-variable">mdev</span> <span class="cm-operator">&gt;</span> <span class="cm-operator">/</span><span class="cm-variable">proc</span><span class="cm-operator">/</span><span class="cm-variable">sys</span><span class="cm-operator">/</span><span class="cm-variable">kernel</span><span class="cm-operator">/</span><span class="cm-variable">hotplug</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">mdev</span> <span class="cm-operator">-</span><span class="cm-variable">s</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">#开机自启动</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">cd</span> <span class="cm-operator">/</span><span class="cm-variable">drivers</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">.<span class="cm-operator">/</span><span class="cm-variable">hello</span> <span class="cm-operator">&amp;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">cd</span> <span class="cm-operator">/</span></span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 437px;"></div><div class="CodeMirror-gutters" style="display: none; height: 437px;"></div></div></div></pre><p>&nbsp;</p><h5><a name="4）网络测试" class="md-header-anchor"></a><span>4）网络测试</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200119746.png" referrerpolicy="no-referrer" alt="image-20230620011945657"></p><p>&nbsp;</p><h4><a name="136-使用nfs挂载根文件系统" class="md-header-anchor"></a><span>1.3.6 使用nfs挂载根文件系统</span></h4><h5><a name="1）boot设置" class="md-header-anchor"></a><span>1）boot设置</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200123005.png" referrerpolicy="no-referrer" alt="image-20230620012348885"></p><p><span>正常来说，应该正常进入根文件系统。</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">环境变量的root值：</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">root=/dev/nfs nfsroot=211.66.11.77:/home/ydwu/linux/nfs/rootfs,proto=tcp rw ip=211.66.11.70:211.66.11.77:211.66.11.254:255.255.255.0::eth0:off</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">设置环境变量的命令：</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=211.66.11.77:/home/ydwu/linux/nfs/rootfs,proto=tcp rw ip=211.66.11.70:211.66.11.77:211.66.11.254:255.255.255.0::eth0:off' //设置 bootargs</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">saveenv //保存环境变量</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 184px;"></div><div class="CodeMirror-gutters" style="display: none; height: 184px;"></div></div></div></pre><p><span>设置完后，用boot命令启动Linux内核。</span></p><p><span>环境变量写入emmc中，所以下次掉电启动之前，只需要用tftp把系统内核镜像zImage和设备树文件传到指定位置，再启动即可。</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">tftp 80800000 zImage</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">tftp 83000000 imx6ull-alientek-emmc.dtb</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">bootz 80800000 - 83000000</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 69px;"></div><div class="CodeMirror-gutters" style="display: none; height: 69px;"></div></div></div></pre><p><span>可以看到，成功挂载根文件系统，计划开机自启动的helloworld脚本也顺利启动了。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200925042.png" referrerpolicy="no-referrer" alt="image-20230620092537957"></p><p>&nbsp;</p><h5><a name="2）使用体验" class="md-header-anchor"></a><span>2）使用体验</span></h5><p><span>通过网络挂载，服务器和开发板的内容会同步。如果运行过程中断网了，那根文件系统就没法被挂载了：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306200955331.png" referrerpolicy="no-referrer" alt="image-20230620095530284"></p><p>&nbsp;</p><h3><a name="14-系统烧写" class="md-header-anchor"></a><span>1.4 系统烧写</span></h3><p><span>主要是使用NXP官方提供的工具，将系统烧写到EMMC上。</span></p><p><span>可以总结为两步：第一步，通过USB_OTG向DDR中下载系统，将firmware目录中的uboot、linux kernel、.dtb这三个文件下载到开发板的DDR中，相当于先在开发板的DDR上启动Linux系统·。第二步，将uboot、linux kernel、.dtb、rootfs这四个文件烧写到EMMC中。</span></p><p>&nbsp;</p><h2><a name="二字符设备驱动开发" class="md-header-anchor"></a><span>二、字符设备驱动开发</span></h2><h3><a name="21-字符设备驱动简介" class="md-header-anchor"></a><span>2.1 字符设备驱动简介</span></h3><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201557362.png" referrerpolicy="no-referrer" alt="image-20230620155723262"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201558611.png" referrerpolicy="no-referrer" alt="image-20230620155820531"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201600490.png" referrerpolicy="no-referrer" alt="image-20230620160055415"></p><p>&nbsp;</p><h4><a name="211-驱动模块的加载和卸载" class="md-header-anchor"></a><span>2.1.1 驱动模块的加载和卸载</span></h4><p><span>主要是通过module_init函数和module_exit函数来注册入口函数和出口函数。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201636428.png" referrerpolicy="no-referrer" alt="image-20230620163645350"></p><p><span>驱动编译完之后的扩展名为.ko，可以通过insmod和modprobe这两个命令来加载。insmod命令不能解决模块的依赖关系，modprobe命令会分析模块的依赖关系，并把所有的依赖模块都加载到内核中。</span></p><p><span>modprobe 命令默认会去/lib/modules/</span><kernel-version><span> 目录中查找模块，比如本书使用的 Linux kernel 的版本号为 4.1.15，因此 modprobe 命令默认会到/lib/modules/4.1.15 这个目录中查找相应的驱动模块，一般自己制作的根文件系统中是不会有这个目录的，所以</span><strong><span>需要自己手动创建</span></strong><span>。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201644078.png" referrerpolicy="no-referrer" alt="image-20230620164436024"></p><p>&nbsp;</p><h4><a name="212-字符设备的注册与注销" class="md-header-anchor"></a><span>2.1.2 字符设备的注册与注销</span></h4><p><span>驱动模块加载成功以后，注册字符设备；卸载驱动模块以后，注销掉字符设备。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201649001.png" referrerpolicy="no-referrer" alt="image-20230620164905922"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201652450.png" referrerpolicy="no-referrer" alt="image-20230620165257371"></p><p>&nbsp;</p><h4><a name="213-实现设备操作的具体函数" class="md-header-anchor"></a><span>2.1.3 实现设备操作的具体函数</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201658123.png" referrerpolicy="no-referrer" alt="image-20230620165803047"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201659156.png" referrerpolicy="no-referrer" alt="image-20230620165936083"></p><p><span>我的理解:</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">关键是 </span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">static struct file_operations test_fop = {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">//指定各种操作函数</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">然后在驱动的入口函数中注册字符设备：</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">retvalue = register_chrdev(200, "chrtest", &amp;test_fops);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">这样，字符设备的操作函数就绑定到了自己写的操作函数里。</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 184px;"></div><div class="CodeMirror-gutters" style="display: none; height: 184px;"></div></div></div></pre><p>&nbsp;</p><h5><a name="补充设备操作函数的原型" class="md-header-anchor"></a><span>补充：设备操作函数的原型</span></h5><p><span>设备的.open .write .read .release函数的原型如下：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//1.read函数</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">ssize_t</span> (<span class="cm-operator">*</span><span class="cm-variable">read</span>) (<span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">file</span>, <span class="cm-variable-3">char</span> <span class="cm-variable">__user</span> <span class="cm-operator">*</span><span class="cm-variable">buf</span>, <span class="cm-variable-3">size_t</span> <span class="cm-variable">count</span>, <span class="cm-variable">loff_t</span> <span class="cm-operator">*</span><span class="cm-variable">pos</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">其中，</span>.<span class="cm-variable">read</span>() <span class="cm-variable">操作的参数分别为：</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">file</span>: <span class="cm-variable">指向表示打开的文件的</span> <span class="cm-variable">file</span> <span class="cm-variable">结构体的指针。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable-3">char</span> <span class="cm-variable">__user</span> <span class="cm-operator">*</span><span class="cm-variable">buf</span>: <span class="cm-variable">指向目标缓冲区的用户空间地址。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable-3">size_t</span> <span class="cm-variable">count</span>: <span class="cm-variable">请求读取数据的字节数。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">loff_t</span> <span class="cm-operator">*</span><span class="cm-variable">pos</span>: <span class="cm-variable">来自</span> <span class="cm-variable">VFS</span> <span class="cm-variable">（Virtual</span> <span class="cm-variable">Filesystem</span> <span class="cm-variable">Switch）层的偏移量，指示从何处开始读取。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">而</span> .<span class="cm-variable">write</span>() <span class="cm-variable">操作的参数分别为：</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//2.write函数</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-def">ssize_t</span> (<span class="cm-operator">*</span><span class="cm-variable">write</span>) (<span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">file</span>, <span class="cm-keyword">const</span> <span class="cm-variable-3">char</span> <span class="cm-variable">__user</span> <span class="cm-operator">*</span><span class="cm-variable">buf</span>, <span class="cm-variable-3">size_t</span> <span class="cm-variable">count</span>, <span class="cm-variable">loff_t</span> <span class="cm-operator">*</span><span class="cm-variable">pos</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">file</span>: <span class="cm-variable">指向表示打开的文件的</span> <span class="cm-variable">file</span> <span class="cm-variable">结构体的指针。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">const</span> <span class="cm-variable-3">char</span> <span class="cm-variable">__user</span> <span class="cm-operator">*</span><span class="cm-variable">buf</span>: <span class="cm-variable">指向源缓冲区的用户空间地址。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable-3">size_t</span> <span class="cm-variable">count</span>: <span class="cm-variable">请求写入数据的字节数。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">loff_t</span> <span class="cm-operator">*</span><span class="cm-variable">pos</span>: <span class="cm-variable">来自</span> <span class="cm-variable">VFS</span> <span class="cm-variable">层的偏移量，指示从何处开始写入。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//需要注意的是，由于 .read() 和 .write() 操作涉及到用户空间和内核空间之间的数据传输，因此我们使用了 __user 修饰符，以表示 buf 参数指向的是用户空间的地址。同时，函数的返回值是 ssize_t 类型，表示实际读取或写入的字节数，如果出现错误则应该返回负数。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//3.open函数 &nbsp; &nbsp;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable-3">int</span> (<span class="cm-operator">*</span><span class="cm-variable">open</span>) (<span class="cm-keyword">struct</span> <span class="cm-def">inode</span> <span class="cm-operator">*</span><span class="cm-variable">inode</span>, <span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">file</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//4.release函数</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable-3">int</span> (<span class="cm-operator">*</span><span class="cm-variable">release</span>) (<span class="cm-keyword">struct</span> <span class="cm-def">inode</span> <span class="cm-operator">*</span><span class="cm-variable">inode</span>, <span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">file</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">其中，</span>.<span class="cm-variable">open</span>() <span class="cm-variable">与</span> .<span class="cm-variable">release</span>() <span class="cm-variable">函数的参数都包括两个指针类型的参数</span> <span class="cm-keyword">struct</span> <span class="cm-def">inode</span> <span class="cm-operator">*</span><span class="cm-variable">inode</span> <span class="cm-variable">和</span> <span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">file。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">struct</span> <span class="cm-def">inode</span> <span class="cm-operator">*</span><span class="cm-variable">inode</span>: </span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">这个参数包含了有关设备文件的元数据，例如所有者、文件大小和权限等信息。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">file</span>: </span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">这个参数表示了一个打开的文件对象，包含了有关文件对象的状态信息，例如文件描述符、文件偏移量等信息。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">.<span class="cm-variable">open</span>() <span class="cm-variable">操作函数会在用户空间应用程序首次打开设备文件时被调用，它返回值为整型。如果成功打开设备文件，应该返回0。否则，应该返回一个负数值，表示打开过程中出现的错误。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">.<span class="cm-variable">release</span>() <span class="cm-variable">操作函数会在设备文件被最后一个引用者关闭时调用，它没有返回值。在这个函数中，驱动程序可以释放分配给打开文件的资源，例如缓冲区或锁等。</span></span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 851px;"></div><div class="CodeMirror-gutters" style="display: none; height: 851px;"></div></div></div></pre><p>&nbsp;</p><h5><a name="对应应用程序中的函数" class="md-header-anchor"></a><span>对应应用程序中的函数</span></h5><p><span>但是应用程序定义的这几个函数，和驱动的不太一样。</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">应用程序中的</span> <span class="cm-def">open</span>()<span class="cm-variable">、write</span>()<span class="cm-variable">、read</span>() <span class="cm-variable">和</span> <span class="cm-def">release</span>() <span class="cm-variable">函数都需要使用系统调用来访问驱动程序中实现的对应功能</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">其函数原型如下：</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable-3">int</span> <span class="cm-def">open</span>(<span class="cm-keyword">const</span> <span class="cm-variable-3">char</span> <span class="cm-variable-3">*</span><span class="cm-variable">path</span>, <span class="cm-variable-3">int</span> <span class="cm-variable">flags</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">ssize_t</span> <span class="cm-def">read</span>(<span class="cm-variable-3">int</span> <span class="cm-variable">fd</span>, <span class="cm-variable-3">void</span> <span class="cm-variable-3">*</span><span class="cm-variable">buf</span>, <span class="cm-variable-3">size_t</span> <span class="cm-variable">count</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">ssize_t</span> <span class="cm-def">write</span>(<span class="cm-variable-3">int</span> <span class="cm-variable">fd</span>, <span class="cm-keyword">const</span> <span class="cm-variable-3">void</span> <span class="cm-variable-3">*</span><span class="cm-variable">buf</span>, <span class="cm-variable-3">size_t</span> <span class="cm-variable">count</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable-3">int</span> <span class="cm-def">release</span>(<span class="cm-variable-3">int</span> <span class="cm-variable">fd</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">其中，open</span>() <span class="cm-variable">函数用于打开设备文件或其他文件，返回文件描述符（file</span> <span class="cm-variable">descriptor）以供后续的读写操作使用。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-def">read</span>() <span class="cm-variable">与</span> <span class="cm-def">write</span>() <span class="cm-variable">分别用于从文件读取数据和向文件写入数据，它们的参数和驱动程序中的对应操作函数类似。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">而</span> <span class="cm-def">release</span>() <span class="cm-variable">函数用于关闭打开的文件。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">需要注意的是，应用程序中的这些函数使用的是用户空间的内存和描述符，而驱动程序中的操作函数使用的是内核空间的内存和描述符。因此，这些函数之间进行数据传输时会涉及到用户空间与内核空间之间的数据拷贝，需要通过系统调用实现。此外，在应用程序中，还需要处理文件访问权限等问题，这些在驱动程序中并不需要考虑。</span></span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 322px;"></div><div class="CodeMirror-gutters" style="display: none; height: 322px;"></div></div></div></pre><p>&nbsp;</p><p><span>应用程序的函数如何与驱动关联：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">在</span> <span class="cm-variable">Linux</span> <span class="cm-variable">内核中，驱动程序与用户空间应用程序之间的接口是通过设备文件（device</span> <span class="cm-variable">file）来实现的。设备文件由内核通过调用</span> <span class="cm-def">device_create</span>() <span class="cm-variable">或</span> <span class="cm-def">cdev_add</span>() <span class="cm-variable">等函数创建，它们通常位于</span> <span class="cm-operator">/</span><span class="cm-variable">dev</span> <span class="cm-variable">目录下，并且其名称与设备的主设备号和次设备号有关。</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">一旦应用程序打开设备文件，内核就会调用设备驱动程序中的</span> .<span class="cm-variable">open</span>() <span class="cm-variable">函数，在其中执行必要的初始化操作并返回成功或失败状态。同样，当应用程序执行读取或写入操作时，内核会调用设备驱动程序中的</span> .<span class="cm-variable">read</span>() <span class="cm-variable">或</span> .<span class="cm-variable">write</span>() <span class="cm-variable">函数，在其中执行数据传输等操作。最后，当应用程序关闭设备文件时，内核会调用设备驱动程序中的</span> .<span class="cm-variable">release</span>() <span class="cm-variable">函数，在其中释放任何内存资源等操作。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">需要注意的是，这些函数的调用是由内核自动完成的，并且其参数的值和类型都是由内核决定的。因此，设备驱动程序中的函数必须遵循正确的参数原型，以便能够被正确地调用。另外，这些函数的返回值具有特殊的含义，例如</span> .<span class="cm-variable">read</span>() <span class="cm-variable">函数应该返回实际读取的字节数，而</span> .<span class="cm-variable">write</span>() <span class="cm-variable">函数应该返回实际写入的字节数。这些返回值对于应用程序的正确性和效率都至关重要。</span></span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 230px;"></div><div class="CodeMirror-gutters" style="display: none; height: 230px;"></div></div></div></pre><p>&nbsp;</p><p>&nbsp;</p><p><span>在应用程序的代码中：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//1.打开LED驱动</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">filename</span> <span class="cm-operator">=</span> <span class="cm-variable">argv</span>[<span class="cm-number">1</span>];</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">fd</span> <span class="cm-operator">=</span> <span class="cm-variable">open</span>(<span class="cm-variable">filename</span>, <span class="cm-variable">O_RDWR</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">if</span>(<span class="cm-variable">fd</span> <span class="cm-operator">&lt;</span> <span class="cm-number">0</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-variable">printf</span>(<span class="cm-string">"file %s open failed!\r\n"</span>, <span class="cm-variable">argv</span>[<span class="cm-number">1</span>]);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-keyword">return</span> <span class="cm-operator">-</span><span class="cm-number">1</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//2.写数据</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">retvalue</span> <span class="cm-operator">=</span> <span class="cm-variable">write</span>(<span class="cm-variable">fd</span>, <span class="cm-variable">databuf</span>, <span class="cm-keyword">sizeof</span>(<span class="cm-variable">databuf</span>));</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">if</span>(<span class="cm-variable">retvalue</span> <span class="cm-operator">&lt;</span> <span class="cm-number">0</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-variable">printf</span>(<span class="cm-string">"LED Control Failed!\r\n"</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-variable">close</span>(<span class="cm-variable">fd</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-keyword">return</span> <span class="cm-operator">-</span><span class="cm-number">1</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//3.关闭</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">retvalue</span> <span class="cm-operator">=</span> <span class="cm-variable">close</span>(<span class="cm-variable">fd</span>); <span class="cm-comment">/* 关闭文件 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">if</span>(<span class="cm-variable">retvalue</span> <span class="cm-operator">&lt;</span> <span class="cm-number">0</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-variable">printf</span>(<span class="cm-string">"file %s close failed!\r\n"</span>, <span class="cm-variable">argv</span>[<span class="cm-number">1</span>]);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-keyword">return</span> <span class="cm-operator">-</span><span class="cm-number">1</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 506px;"></div><div class="CodeMirror-gutters" style="display: none; height: 506px;"></div></div></div></pre><p>&nbsp;</p><p>&nbsp;</p><h4><a name="214-添加license和作者信息" class="md-header-anchor"></a><span>2.1.4 添加LICENSE和作者信息</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201707826.png" referrerpolicy="no-referrer" alt="image-20230620170706750"></p><p>&nbsp;</p><h4><a name="215-linux设备号" class="md-header-anchor"></a><span>2.1.5 Linux设备号</span></h4><h5><a name="1）组成" class="md-header-anchor"></a><span>1）组成</span></h5><p><span>是一个uint32_t，高12位是主设备号，低20位是次设备号。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201711961.png" referrerpolicy="no-referrer" alt="image-20230620171148898"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201712449.png" referrerpolicy="no-referrer" alt="image-20230620171204391"></p><p>&nbsp;</p><h5><a name="2）设备号的分配" class="md-header-anchor"></a><span>2）设备号的分配</span></h5><p><span>使用“cat /proc/devices”命令即可查看当前系统中所有已经使用了的设备号</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201714503.png" referrerpolicy="no-referrer" alt="image-20230620171437431"></p><p>&nbsp;</p><h3><a name="22-chrdevbase字符设备驱动开发实验" class="md-header-anchor"></a><span>2.2 chrdevbase字符设备驱动开发实验</span></h3><p><span>创建一个虚拟的字符设备chrdevbase。步骤大致如下。</span></p><h4><a name="221-创建vscode工程" class="md-header-anchor"></a><span>2.2.1 创建vscode工程</span></h4><p><span>创建一个名为 1_chrdevbase 的文件夹，并将其设置为工作区。</span></p><p><span>在里面新建一个chrdevbase.c文件，后续在这里面写驱动程序。</span></p><p>&nbsp;</p><h4><a name="222-添加头文件路径" class="md-header-anchor"></a><span>2.2.2 添加头文件路径</span></h4><p><span>按下ctrl+shift+p，打开“C/C++: Edit configurations(JSON) ”，includePath 表示头文件路径，需要将 Linux 源码里面的头文件路径添加进来。</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">includePath": [</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  "${workspaceFolder}/**",</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  "/home/ydwu/linux/kernel/nxp_linux_new/include",</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  "/home/ydwu/linux/kernel/nxp_linux_new/arch/arm/include",</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  "/home/ydwu/linux/kernel/nxp_linux_new/arch/arm/include/generated/"</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">],</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 138px;"></div><div class="CodeMirror-gutters" style="display: none; height: 138px;"></div></div></div></pre><p><span>分别是开发板所使用的Linux 源码下的 include、arch/arm/include 和 arch/arm/include/generated 这三个目录的路径。</span></p><p><strong><span>补充：</span></strong></p><p><span>在 Linux 内核源代码的 </span><code>include</code><span> 目录下，存放了大量的头文件，而 </span><code>arch/arm/include</code><span> 和 </span><code>arch/arm/include/generated</code><span> 这两个目录都是与 ARM 架构相关的头文件目录。</span></p><p><span>其中 </span><code>arch/arm/include</code><span> 目录中存放的是与 ARM 架构有关的一些通用的头文件，这些头文件不依赖于具体的 SoC 芯片或板子。例如 </span><code>asm/gpio.h</code><span> 就定义了 GPIO 相关的操作宏，适用于所有 ARM 架构的处理器。</span></p><p><span>而 </span><code>arch/arm/include/generated</code><span> 目录中存放的是自动生成的一些头文件，这些头文件会根据具体的硬件平台自动进行生成，以满足不同硬件平台的需要。例如 </span><code>asm/regs-irq.h</code><span> 文件中定义了 IRQ 寄存器的宏定义，这些宏定义是根据不同的 SoC 芯片进行生成的。</span></p><p>&nbsp;</p><h4><a name="223-编写程序" class="md-header-anchor"></a><span>2.2.3 编写程序</span></h4><h5><a name="1）驱动程序" class="md-header-anchor"></a><span>1）驱动程序</span></h5><p><span>chrdevbase.c，参考正点原子教程的写法，代码如下：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include &lt;linux/types.h&gt;</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include &lt;linux/kernel.h&gt;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include &lt;linux/delay.h&gt;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include &lt;linux/ide.h&gt;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include &lt;linux/init.h&gt;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include &lt;linux/module.h&gt;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/***************************************************************</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">文件名<span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: chrdevbase.c</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">作者<span class="cm-tab" role="presentation" cm-text="	">  </span>  <span class="cm-tab" role="presentation" cm-text="	">  </span>: 左忠凯</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">版本<span class="cm-tab" role="presentation" cm-text="	">  </span> &nbsp; <span class="cm-tab" role="presentation" cm-text="	"> </span>: V1.0</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">描述<span class="cm-tab" role="presentation" cm-text="	">  </span> &nbsp; <span class="cm-tab" role="presentation" cm-text="	"> </span>: chrdevbase驱动文件。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">其他<span class="cm-tab" role="presentation" cm-text="	">  </span> &nbsp; <span class="cm-tab" role="presentation" cm-text="	"> </span>: 无</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">论坛 <span class="cm-tab" role="presentation" cm-text="	"> </span> &nbsp; <span class="cm-tab" role="presentation" cm-text="	"> </span>: www.openedv.com</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">日志<span class="cm-tab" role="presentation" cm-text="	">  </span> &nbsp; <span class="cm-tab" role="presentation" cm-text="	"> </span>: 初版V1.0 2019/1/30 左忠凯创建</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">***************************************************************/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#define CHRDEVBASE_MAJOR<span class="cm-tab" role="presentation" cm-text="	">    </span>200<span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span></span><span class="cm-comment">/* 主设备号 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#define CHRDEVBASE_NAME<span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span>"chrdevbase" <span class="cm-tab" role="presentation" cm-text="	">   </span></span><span class="cm-comment">/* 设备名 &nbsp; &nbsp; */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable-3">char</span> <span class="cm-variable">readbuf</span>[<span class="cm-number">100</span>];<span class="cm-tab" role="presentation" cm-text="	">   </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 读缓冲区 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable-3">char</span> <span class="cm-variable">writebuf</span>[<span class="cm-number">100</span>];<span class="cm-tab" role="presentation" cm-text="	">  </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 写缓冲区 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable-3">char</span> <span class="cm-variable">kerneldata</span>[] <span class="cm-operator">=</span> {<span class="cm-string">"kernel data!"</span>};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/*</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @description<span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 打开设备</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - inode <span class="cm-tab" role="presentation" cm-text="	">  </span>: 传递给驱动的inode</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - filp <span class="cm-tab" role="presentation" cm-text="	">   </span>: 设备文件，file结构体有个叫做private_data的成员变量</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* <span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>  一般在open的时候将private_data指向设备结构体。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @return <span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 0 成功;其他 失败</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable-3">int</span> <span class="cm-def">chrdevbase_open</span>(<span class="cm-keyword">struct</span> <span class="cm-def">inode</span> <span class="cm-operator">*</span><span class="cm-variable">inode</span>, <span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">filp</span>)</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">//printk("chrdevbase open!\r\n");</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-number">0</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/*</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @description<span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 从设备读取数据 </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - filp <span class="cm-tab" role="presentation" cm-text="	">   </span>: 要打开的设备文件(文件描述符)</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - buf <span class="cm-tab" role="presentation" cm-text="	">    </span>: 返回给用户空间的数据缓冲区</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - cnt <span class="cm-tab" role="presentation" cm-text="	">    </span>: 要读取的数据长度</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - offt <span class="cm-tab" role="presentation" cm-text="	">   </span>: 相对于文件首地址的偏移</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @return <span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 读取的字节数，如果为负值，表示读取失败</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable">ssize_t</span> <span class="cm-def">chrdevbase_read</span>(<span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">filp</span>, <span class="cm-variable-3">char</span> <span class="cm-variable">__user</span> <span class="cm-operator">*</span><span class="cm-variable">buf</span>, <span class="cm-variable-3">size_t</span> <span class="cm-variable">cnt</span>, <span class="cm-variable">loff_t</span> <span class="cm-operator">*</span><span class="cm-variable">offt</span>)</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable-3">int</span> <span class="cm-variable">retvalue</span> <span class="cm-operator">=</span> <span class="cm-number">0</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 向用户空间发送数据 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">memcpy</span>(<span class="cm-variable">readbuf</span>, <span class="cm-variable">kerneldata</span>, <span class="cm-keyword">sizeof</span>(<span class="cm-variable">kerneldata</span>));</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">retvalue</span> <span class="cm-operator">=</span> <span class="cm-variable">copy_to_user</span>(<span class="cm-variable">buf</span>, <span class="cm-variable">readbuf</span>, <span class="cm-variable">cnt</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span>(<span class="cm-variable">retvalue</span> <span class="cm-operator">==</span> <span class="cm-number">0</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printk</span>(<span class="cm-string">"kernel senddata ok!\r\n"</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}<span class="cm-keyword">else</span>{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printk</span>(<span class="cm-string">"kernel senddata failed!\r\n"</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">//printk("chrdevbase read!\r\n");</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-number">0</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/*</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @description<span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 向设备写数据 </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - filp <span class="cm-tab" role="presentation" cm-text="	">   </span>: 设备文件，表示打开的文件描述符</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - buf <span class="cm-tab" role="presentation" cm-text="	">    </span>: 要写给设备写入的数据</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - cnt <span class="cm-tab" role="presentation" cm-text="	">    </span>: 要写入的数据长度</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - offt <span class="cm-tab" role="presentation" cm-text="	">   </span>: 相对于文件首地址的偏移</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @return <span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 写入的字节数，如果为负值，表示写入失败</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable">ssize_t</span> <span class="cm-def">chrdevbase_write</span>(<span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">filp</span>, <span class="cm-keyword">const</span> <span class="cm-variable-3">char</span> <span class="cm-variable">__user</span> <span class="cm-operator">*</span><span class="cm-variable">buf</span>, <span class="cm-variable-3">size_t</span> <span class="cm-variable">cnt</span>, <span class="cm-variable">loff_t</span> <span class="cm-operator">*</span><span class="cm-variable">offt</span>)</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable-3">int</span> <span class="cm-variable">retvalue</span> <span class="cm-operator">=</span> <span class="cm-number">0</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 接收用户空间传递给内核的数据并且打印出来 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">retvalue</span> <span class="cm-operator">=</span> <span class="cm-variable">copy_from_user</span>(<span class="cm-variable">writebuf</span>, <span class="cm-variable">buf</span>, <span class="cm-variable">cnt</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span>(<span class="cm-variable">retvalue</span> <span class="cm-operator">==</span> <span class="cm-number">0</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printk</span>(<span class="cm-string">"kernel recevdata:%s\r\n"</span>, <span class="cm-variable">writebuf</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}<span class="cm-keyword">else</span>{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printk</span>(<span class="cm-string">"kernel recevdata failed!\r\n"</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">//printk("chrdevbase write!\r\n");</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-number">0</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/*</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @description<span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 关闭/释放设备</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - filp <span class="cm-tab" role="presentation" cm-text="	">   </span>: 要关闭的设备文件(文件描述符)</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @return <span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 0 成功;其他 失败</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable-3">int</span> <span class="cm-def">chrdevbase_release</span>(<span class="cm-keyword">struct</span> <span class="cm-def">inode</span> <span class="cm-operator">*</span><span class="cm-variable">inode</span>, <span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">filp</span>)</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">//printk("chrdevbase release！\r\n");</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-number">0</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/*</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">* 设备操作函数结构体</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-keyword">struct</span> <span class="cm-def">file_operations</span> <span class="cm-def">chrdevbase_fops</span> <span class="cm-operator">=</span> {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">owner</span> <span class="cm-operator">=</span> <span class="cm-variable">THIS_MODULE</span>,<span class="cm-tab" role="presentation" cm-text="	">   </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">open</span> <span class="cm-operator">=</span> <span class="cm-variable">chrdevbase_open</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">read</span> <span class="cm-operator">=</span> <span class="cm-variable">chrdevbase_read</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">write</span> <span class="cm-operator">=</span> <span class="cm-variable">chrdevbase_write</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">release</span> <span class="cm-operator">=</span> <span class="cm-variable">chrdevbase_release</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/*</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @description<span class="cm-tab" role="presentation" cm-text="	"> </span>: 驱动入口函数 </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param <span class="cm-tab" role="presentation" cm-text="	">  </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 无</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @return <span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 0 成功;其他 失败</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable-3">int</span> <span class="cm-variable">__init</span> <span class="cm-def">chrdevbase_init</span>(<span class="cm-variable-3">void</span>)</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable-3">int</span> <span class="cm-variable">retvalue</span> <span class="cm-operator">=</span> <span class="cm-number">0</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 注册字符设备驱动 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">retvalue</span> <span class="cm-operator">=</span> <span class="cm-variable">register_chrdev</span>(<span class="cm-variable">CHRDEVBASE_MAJOR</span>, <span class="cm-variable">CHRDEVBASE_NAME</span>, <span class="cm-operator">&amp;</span><span class="cm-variable">chrdevbase_fops</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span>(<span class="cm-variable">retvalue</span> <span class="cm-operator">&lt;</span> <span class="cm-number">0</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printk</span>(<span class="cm-string">"chrdevbase driver register failed\r\n"</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printk</span>(<span class="cm-string">"chrdevbase init!\r\n"</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-number">0</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/*</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @description<span class="cm-tab" role="presentation" cm-text="	"> </span>: 驱动出口函数</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param <span class="cm-tab" role="presentation" cm-text="	">  </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 无</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @return <span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 无</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable-3">void</span> <span class="cm-variable">__exit</span> <span class="cm-def">chrdevbase_exit</span>(<span class="cm-variable-3">void</span>)</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 注销字符设备驱动 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">unregister_chrdev</span>(<span class="cm-variable">CHRDEVBASE_MAJOR</span>, <span class="cm-variable">CHRDEVBASE_NAME</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printk</span>(<span class="cm-string">"chrdevbase exit!\r\n"</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/* </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">* 将上面两个函数指定为驱动的入口和出口函数 </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">module_init</span>(<span class="cm-variable">chrdevbase_init</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">module_exit</span>(<span class="cm-variable">chrdevbase_exit</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/* </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">* LICENSE和作者信息</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">MODULE_LICENSE</span>(<span class="cm-string">"GPL"</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">MODULE_AUTHOR</span>(<span class="cm-string">"yudong.wu"</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 3427px;"></div><div class="CodeMirror-gutters" style="display: none; height: 3427px;"></div></div></div></pre><p><span>正点原子对代码的解释：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306201803100.png" referrerpolicy="no-referrer" alt="image-20230620180341002"></p><p>&nbsp;</p><p><span>我的理解：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">稍后再补充。</span></pre></div></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 23px;"></div><div class="CodeMirror-gutters" style="display: none; height: 23px;"></div></div></div></pre><p>&nbsp;</p><h5><a name="2）应用程序" class="md-header-anchor"></a><span>2）应用程序</span></h5><p><span>编写测试 APP 就是编写 Linux 应用，需要用到 C 库里面和文件操作有关的一些函数，比如 open、read、write 和 close 这四个函数。</span></p><p><strong><span>我的概括：</span></strong></p><p><span>open的参数为2个：要打开的设备或者文件名，文件打开的模式</span></p><p><span>read和write的参数都是3个：文件描述符，读取/写的数据（指针），要读/写的长度。</span></p><p><span>close的参数为1个：要关闭的文件描述符</span></p><p>&nbsp;</p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202012357.png" referrerpolicy="no-referrer" alt="image-20230620201250267"></p><p>&nbsp;</p><p><span>正点原子教程给的应用代码：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include "stdio.h"</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include "unistd.h"</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include "sys/types.h"</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include "sys/stat.h"</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include "fcntl.h"</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include "stdlib.h"</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#include "string.h"</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/***************************************************************</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">Copyright © ALIENTEK Co., Ltd. 1998-2029. All rights reserved.</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">文件名<span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: chrdevbaseApp.c</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">作者<span class="cm-tab" role="presentation" cm-text="	">  </span>  <span class="cm-tab" role="presentation" cm-text="	">  </span>: 左忠凯</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">版本<span class="cm-tab" role="presentation" cm-text="	">  </span> &nbsp; <span class="cm-tab" role="presentation" cm-text="	"> </span>: V1.0</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">描述<span class="cm-tab" role="presentation" cm-text="	">  </span> &nbsp; <span class="cm-tab" role="presentation" cm-text="	"> </span>: chrdevbase驱测试APP。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">其他<span class="cm-tab" role="presentation" cm-text="	">  </span> &nbsp; <span class="cm-tab" role="presentation" cm-text="	"> </span>: 使用方法：./chrdevbase /dev/chrdevbase &lt;1&gt;|&lt;2&gt;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">  <span class="cm-tab" role="presentation" cm-text="	">  </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span> <span class="cm-comment">argv[2] 1:读文件</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;">  <span class="cm-tab" role="presentation" cm-text="	">  </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span> <span class="cm-comment">argv[2] 2:写文件<span class="cm-tab" role="presentation" cm-text="	">  </span><span class="cm-tab" role="presentation" cm-text="	">    </span></span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">论坛 <span class="cm-tab" role="presentation" cm-text="	"> </span> &nbsp; <span class="cm-tab" role="presentation" cm-text="	"> </span>: www.openedv.com</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-comment">日志<span class="cm-tab" role="presentation" cm-text="	">  </span> &nbsp; <span class="cm-tab" role="presentation" cm-text="	"> </span>: 初版V1.0 2019/1/30 左忠凯创建</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">***************************************************************/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable-3">char</span> <span class="cm-variable">usrdata</span>[] <span class="cm-operator">=</span> {<span class="cm-string">"usr data!"</span>};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/*</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @description<span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: main主程序</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - argc <span class="cm-tab" role="presentation" cm-text="	">   </span>: argv数组元素个数</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @param - argv <span class="cm-tab" role="presentation" cm-text="	">   </span>: 具体参数</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"> <span class="cm-comment">* @return <span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>: 0 成功;其他 失败</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-comment">*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable-3">int</span> <span class="cm-def">main</span>(<span class="cm-variable-3">int</span> <span class="cm-variable">argc</span>, <span class="cm-variable-3">char</span> <span class="cm-variable-3">*</span><span class="cm-variable">argv</span>[])</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable-3">int</span> <span class="cm-variable">fd</span>, <span class="cm-variable">retvalue</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable-3">char</span> <span class="cm-variable-3">*</span><span class="cm-variable">filename</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable-3">char</span> <span class="cm-variable">readbuf</span>[<span class="cm-number">100</span>], <span class="cm-variable">writebuf</span>[<span class="cm-number">100</span>];</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span>(<span class="cm-variable">argc</span> <span class="cm-operator">!=</span> <span class="cm-number">3</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printf</span>(<span class="cm-string">"Error Usage!\r\n"</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-operator">-</span><span class="cm-number">1</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">filename</span> <span class="cm-operator">=</span> <span class="cm-variable">argv</span>[<span class="cm-number">1</span>];</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 打开驱动文件 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">fd</span> &nbsp;<span class="cm-operator">=</span> <span class="cm-variable">open</span>(<span class="cm-variable">filename</span>, <span class="cm-variable">O_RDWR</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span>(<span class="cm-variable">fd</span> <span class="cm-operator">&lt;</span> <span class="cm-number">0</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printf</span>(<span class="cm-string">"Can't open file %s\r\n"</span>, <span class="cm-variable">filename</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-operator">-</span><span class="cm-number">1</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span>(<span class="cm-variable">atoi</span>(<span class="cm-variable">argv</span>[<span class="cm-number">2</span>]) <span class="cm-operator">==</span> <span class="cm-number">1</span>){ <span class="cm-comment">/* 从驱动文件读取数据 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">retvalue</span> <span class="cm-operator">=</span> <span class="cm-variable">read</span>(<span class="cm-variable">fd</span>, <span class="cm-variable">readbuf</span>, <span class="cm-number">50</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span>(<span class="cm-variable">retvalue</span> <span class="cm-operator">&lt;</span> <span class="cm-number">0</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printf</span>(<span class="cm-string">"read file %s failed!\r\n"</span>, <span class="cm-variable">filename</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>}<span class="cm-keyword">else</span>{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/*  读取成功，打印出读取成功的数据 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printf</span>(<span class="cm-string">"read data:%s\r\n"</span>,<span class="cm-variable">readbuf</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span>(<span class="cm-variable">atoi</span>(<span class="cm-variable">argv</span>[<span class="cm-number">2</span>]) <span class="cm-operator">==</span> <span class="cm-number">2</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-tab" role="presentation" cm-text="	">   </span><span class="cm-comment">/* 向设备驱动写数据 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">memcpy</span>(<span class="cm-variable">writebuf</span>, <span class="cm-variable">usrdata</span>, <span class="cm-keyword">sizeof</span>(<span class="cm-variable">usrdata</span>));</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">retvalue</span> <span class="cm-operator">=</span> <span class="cm-variable">write</span>(<span class="cm-variable">fd</span>, <span class="cm-variable">writebuf</span>, <span class="cm-number">50</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span>(<span class="cm-variable">retvalue</span> <span class="cm-operator">&lt;</span> <span class="cm-number">0</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printf</span>(<span class="cm-string">"write file %s failed!\r\n"</span>, <span class="cm-variable">filename</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 关闭设备 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">retvalue</span> <span class="cm-operator">=</span> <span class="cm-variable">close</span>(<span class="cm-variable">fd</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span>(<span class="cm-variable">retvalue</span> <span class="cm-operator">&lt;</span> <span class="cm-number">0</span>){</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printf</span>(<span class="cm-string">"Can't close file %s\r\n"</span>, <span class="cm-variable">filename</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-operator">-</span><span class="cm-number">1</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-number">0</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 1748px;"></div><div class="CodeMirror-gutters" style="display: none; height: 1748px;"></div></div></div></pre><p><span>代码理解：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202025502.png" referrerpolicy="no-referrer" alt="image-20230620202526429"></p><p>&nbsp;</p><h4><a name="224-编译" class="md-header-anchor"></a><span>2.2.4 编译</span></h4><h5><a name="1）编译驱动程序" class="md-header-anchor"></a><span>1）编译驱动程序</span></h5><p><strong><span>注意：</span></strong><span> 因为编译用到了Linux内核的源码，所以在Linux源码的顶层Makefile中，要指定ARCH和CROSS_COMPILE的值，否则直接用make -j4来编译驱动会报错。</span></p><p>&nbsp;</p><p><span>首先编译驱动程序，也就是 chrdevbase.c 这个文件，我们需要将其编译为.ko 模块，创建Makefile 文件，然后在其中输入如下内容：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202029594.png" referrerpolicy="no-referrer" alt="image-20230620202954512"></p><p>&nbsp;</p><h5><a name="2）编译测试app" class="md-header-anchor"></a><span>2）编译测试APP</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202030310.png" referrerpolicy="no-referrer" alt="image-20230620203033241"></p><p>&nbsp;</p><h4><a name="225-运行" class="md-header-anchor"></a><span>2.2.5 运行</span></h4><h5><a name="1）加载驱动模块" class="md-header-anchor"></a><span>1）加载驱动模块</span></h5><p><span>在根文件系统中，创建/lib/modules/4.1.15文件夹（4.1.15是Linux内核的版本），输入命令把驱动文件传到这个文件夹里：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">sudo cp chrdevbase.ko chrdevbaseApp /home/ydwu/linux/nfs/rootfs/lib/modules/4.1.15/ -f</span></pre></div></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 23px;"></div><div class="CodeMirror-gutters" style="display: none; height: 23px;"></div></div></div></pre><p><span>加载完后，在开发板上启动。</span></p><p><span>进入/lib/modules/4.1.15这个文件夹，输入</span><strong><span>insmod chrdevbase.ko</span></strong><span> 或者 </span><strong><span>modprobe chrdevbase.ko</span></strong><span> 来加载驱动。</span></p><p><span>如果缺少modules.dep这个文件，直接输入 </span><strong><span>depmod</span></strong><span> 命令即可自动生成modules.dep。</span></p><p><span>之后再加载驱动，可以看到驱动被成功加载。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202208307.png" referrerpolicy="no-referrer" alt="image-20230620220840225"></p><p><span>输入lsmod，可以查看当前系统存在的模块。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202209375.png" referrerpolicy="no-referrer" alt="image-20230620220950314"></p><p><span>输入 cat /proc/devices ，可以查看当前系统存在的设备。可以看到，设备号为200的目标设备确实存在。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202210645.png" referrerpolicy="no-referrer" alt="image-20230620221049582"></p><p>&nbsp;</p><h5><a name="2）创建设备节点文件" class="md-header-anchor"></a><span>2）创建设备节点文件</span></h5><p><span>应用层操作设备，实际上是操作设备节点文件。通过指定主设备号，来判断是什么设备。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202213964.png" referrerpolicy="no-referrer" alt="image-20230620221327891"></p><p>&nbsp;</p><h5><a name="3）chrdevbase操作测试" class="md-header-anchor"></a><span>3）chrdevbase操作测试</span></h5><p><span>切回到/lib/modules/4.1.15目录中，运行chrdevbaseApp文件，对设备节点进行操作。</span></p><ul><li><span>读操作</span></li></ul><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202223891.png" referrerpolicy="no-referrer" alt="image-20230620222301828"></p><p><span>上面那句是驱动程序中的的chrdevbase_read函数输出的信息。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202225960.png" referrerpolicy="no-referrer" alt="image-20230620222501889"></p><p><span>下面那句是应用程序中读到的数据。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202225515.png" referrerpolicy="no-referrer" alt="image-20230620222558399"></p><p>&nbsp;</p><ul><li><span>写操作</span></li></ul><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202227647.png" referrerpolicy="no-referrer" alt="image-20230620222719588"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202227567.png" referrerpolicy="no-referrer" alt="image-20230620222743506"></p><p>&nbsp;</p><h5><a name="4）卸载驱动模块" class="md-header-anchor"></a><span>4）卸载驱动模块</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306202228781.png" referrerpolicy="no-referrer" alt="image-20230620222853714"></p><p>&nbsp;</p><h4><a name="225-知识补充驱动入口函数前的-init-和出口函数前的-exit" class="md-header-anchor"></a><span>2.2.5 知识补充：驱动入口函数前的 _init 和出口函数前的 __exit</span></h4><p><span>在 Linux 内核驱动开发中，</span><code>__init</code><span> 和 </span><code>__exit</code><span> 是两个宏，用于标记入口函数和出口函数。它们在模块初始化和清除时起到特殊的作用。</span></p><ol start='' ><li><p><code>__init</code><span> 宏：</span></p><ul><li><span>当一个驱动模块被加载到内核时，其中标记为 </span><code>__init</code><span> 的函数会在初始化期间被调用。</span></li><li><span>这些函数在驱动注册和初始化阶段执行，一旦初始化完成，它们的代码将不再需要。</span></li><li><code>__init</code><span> 函数的执行过程中可以分配临时的资源，但在该函数返回后，这些资源将被释放以节省内存。</span></li></ul></li><li><p><code>__exit</code><span> 宏：</span></p><ul><li><span>当一个驱动模块被从内核中卸载时，其中标记为 </span><code>__exit</code><span> 的函数会在卸载期间被调用。</span></li><li><span>这些函数在驱动清理和卸载阶段执行，用于释放和清除驱动初始化时分配的资源。</span></li><li><code>__exit</code><span> 函数的执行过程中，会释放之前通过 </span><code>__init</code><span> 函数分配的资源，以确保在卸载模块后不会留下垃圾或内存泄漏。</span></li></ul></li></ol><p><span>它们的作用是在内核模块的初始化和清除过程中准确地标识相应的函数，并根据需要执行相应的操作。这样做的好处是可以节省内存并提高系统的整体性能。</span></p><p><span>使用 </span><code>__init</code><span> 和 </span><code>__exit</code><span> 标记函数并不是必须的，尤其是对于静态编译进内核的驱动来说。然而，对于作为模块加载的驱动来说，使用这些宏可以帮助内核优化内存和性能，并确保正确执行初始化和清除操作。因此，在编写可加载的内核模块时，建议使用 </span><code>__init</code><span> 和 </span><code>__exit</code><span> 来标记相应的函数。</span></p><p>&nbsp;</p><p>&nbsp;</p><h3><a name="23-嵌入式linux-led驱动开发实验" class="md-header-anchor"></a><span>2.3 嵌入式Linux LED驱动开发实验</span></h3><p><span>一般都是在驱动的入口函数作初始化配置。</span></p><p><span>本实验还是用传统的，配置寄存器和IO口的方式，进行初始化，简单了解下即可。</span></p><h4><a name="231-led灯驱动原理" class="md-header-anchor"></a><span>2.3.1 LED灯驱动原理</span></h4><h5><a name="1）地址映射" class="md-header-anchor"></a><span>1）地址映射</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306210940962.png" referrerpolicy="no-referrer" alt="image-20230621094052832"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306210943438.png" referrerpolicy="no-referrer" alt="image-20230621094344356"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306210944987.png" referrerpolicy="no-referrer" alt="image-20230621094401936"></p><p><strong><span>我的理解：</span></strong></p><p><span>ioremap函数，用于实现从物理地址变换到虚拟地址。该函数的参数实际是2个，要映射的物理首地址，映射的长度。</span></p><p><span>iounmap函数，用于取消映射的虚拟地址空间首地址，该函数的参数是要取消的虚拟地址。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211000753.png" referrerpolicy="no-referrer" alt="image-20230621100004686"></p><p>&nbsp;</p><h4><a name="232-程序编写" class="md-header-anchor"></a><span>2.3.2 程序编写</span></h4><h5><a name="1）驱动程序-n2071" class="md-header-anchor"></a><span>1）驱动程序</span></h5><p><strong><span>我的理解：</span></strong></p><p><span>在write或者read操作的时候，执行实际操作。比如在本实验中，led_write函数是进行写操作的，改变led灯的状态。</span></p><p><span>在驱动入口函数处，做外设初始化（如寄存器地址映射等），以及注册设备驱动。在驱动出口函数处取消地址映射、注销设备驱动</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211002324.png" referrerpolicy="no-referrer" alt="image-20230621100231252"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211002895.png" referrerpolicy="no-referrer" alt="image-20230621100258824"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211003787.png" referrerpolicy="no-referrer" alt="image-20230621100321716"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211003253.png" referrerpolicy="no-referrer" alt="image-20230621100339181"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211004323.png" referrerpolicy="no-referrer" alt="image-20230621100417253"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211004968.png" referrerpolicy="no-referrer" alt="image-20230621100437905"></p><p>&nbsp;</p><h5><a name="2）应用程序-n2082" class="md-header-anchor"></a><span>2）应用程序</span></h5><p><span>led 驱动加载成功以后手动创建/dev/led 节点，应用 APP 通过操作/dev/led文件来完成对 LED 设备的控制。向/dev/led 文件写 0 表示关闭 LED 灯，写 1 表示打开 LED 灯。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211033123.png" referrerpolicy="no-referrer" alt="image-20230621103321050"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211033444.png" referrerpolicy="no-referrer" alt="image-20230621103338399"></p><p>&nbsp;</p><h4><a name="233-运行测试" class="md-header-anchor"></a><span>2.3.3 运行测试</span></h4><p><span>首先，把编译好的.ko驱动程序和ledApp应用程序放到根文件系统对应目录下：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">sudo cp led.ko ledApp /home/ydwu/linux/nfs/rootfs/lib/modules/4.1.15 -f</span></pre></div></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 23px;"></div><div class="CodeMirror-gutters" style="display: none; height: 23px;"></div></div></div></pre><p><span>然后，在开发板加载驱动程序：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">depmod</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">modprobe led.ko</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 46px;"></div><div class="CodeMirror-gutters" style="display: none; height: 46px;"></div></div></div></pre><p><span>创建设备节点：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">mknod /dev/led c 200 0</span></pre></div></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 23px;"></div><div class="CodeMirror-gutters" style="display: none; height: 23px;"></div></div></div></pre><p><span>开关led灯：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">./ledApp /dev/led 1</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">./ledApp /dev/led 0</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 46px;"></div><div class="CodeMirror-gutters" style="display: none; height: 46px;"></div></div></div></pre><p>&nbsp;</p><h3><a name="24-新字符设备驱动实验" class="md-header-anchor"></a><span>2.4 新字符设备驱动实验</span></h3><h4><a name="241-新字符设备驱动原理" class="md-header-anchor"></a><span>2.4.1 新字符设备驱动原理</span></h4><h5><a name="1）新设备号分配" class="md-header-anchor"></a><span>1）新设备号分配</span></h5><p><span>register_chrdev 和 unregister_chrdev 这两个函数是老版本驱动使用的函数，现在新的字符设备驱动已经不再使用这两个函数，而是使用Linux内核推荐的新字符设备驱动API函数。</span></p><p><strong><span>MKDEV</span></strong><span>函数用于已经定义主设备号的情况；</span></p><p><strong><span>MAJOR</span></strong><span>和</span><strong><span>MINOR</span></strong><span>用于没定义设备号要申请设备号的情况。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211127555.png" referrerpolicy="no-referrer" alt="image-20230621112734487"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211127421.png" referrerpolicy="no-referrer" alt="image-20230621112751366"></p><p>&nbsp;</p><h5><a name="2）新字符设备注册" class="md-header-anchor"></a><span>2）新字符设备注册</span></h5><ul><li><span>字符设备结构</span></li></ul><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211205396.png" referrerpolicy="no-referrer" alt="image-20230621120525331"></p><p>&nbsp;</p><ul><li><span>cdev_init函数</span></li></ul><p><span>用来对字符设备cdev变量进行初始化。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211239648.png" referrerpolicy="no-referrer" alt="image-20230621123917585"></p><p>&nbsp;</p><ul><li><span>cdev_add函数</span></li></ul><p><span>用于向Linux系统添加了字符设备（cdev结构体变量），在用cdev_init函数完成初始化后，调用此函数。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211244124.png" referrerpolicy="no-referrer" alt="image-20230621124402055"></p><p>&nbsp;</p><ul><li><span>cdev_del函数</span></li></ul><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211244283.png" referrerpolicy="no-referrer" alt="image-20230621124445219"></p><p>&nbsp;</p><h4><a name="242-自动创建设备节点" class="md-header-anchor"></a><span>2.4.2 自动创建设备节点</span></h4><h5><a name="1）mdev机制" class="md-header-anchor"></a><span>1）mdev机制</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211248428.png" referrerpolicy="no-referrer" alt="image-20230621124810354"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211248626.png" referrerpolicy="no-referrer" alt="image-20230621124829570"></p><p>&nbsp;</p><h5><a name="2）创建和删除类" class="md-header-anchor"></a><span>2）创建和删除类</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211250966.png" referrerpolicy="no-referrer" alt="image-20230621125009889"></p><p><span>class_create函数用于创建类，2个参数，owner一般是THIS_MODULE，name是类名字。</span></p><p><span>class_destory函数用于删除类，1个参数，就是要删除的类。</span></p><p>&nbsp;</p><h5><a name="3）创建删除设备" class="md-header-anchor"></a><span>3）创建删除设备</span></h5><p><span>使用device_create函数创建设备</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211254258.png" referrerpolicy="no-referrer" alt="image-20230621125413189"></p><p>&nbsp;</p><h5><a name="4）示例代码" class="md-header-anchor"></a><span>4）示例代码</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211255984.png" referrerpolicy="no-referrer" alt="image-20230621125534903"></p><p>&nbsp;</p><h4><a name="243-设置文件私有数据" class="md-header-anchor"></a><span>2.4.3 设置文件私有数据</span></h4><p><span>将设备的属性编写成一个结构体，编写驱动open函数的时候，将设备结构体作为私有数据添加到设备文件中。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211257545.png" referrerpolicy="no-referrer" alt="image-20230621125726466"></p><p>&nbsp;</p><h4><a name="244-程序编写" class="md-header-anchor"></a><span>2.4.4 程序编写</span></h4><h5><a name="1）驱动程序-n2151" class="md-header-anchor"></a><span>1）驱动程序</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211258995.png" referrerpolicy="no-referrer" alt="image-20230621125821916"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211258762.png" referrerpolicy="no-referrer" alt="image-20230621125839676"></p><p><span>......</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211259192.png" referrerpolicy="no-referrer" alt="image-20230621125921111"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211259662.png" referrerpolicy="no-referrer" alt="image-20230621125958572"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211300568.png" referrerpolicy="no-referrer" alt="image-20230621130057506"></p><p><strong><span>我的理解：</span></strong></p><p><span>和旧驱动的区别在于：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">1.需要定义设备结构体</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">2.在open函数中，要设置filp-&gt;private_data指向设备对象，如 </span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">filp-&gt;private_data = &amp;newchrled;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">3.在驱动入口函数中，注册字符设备驱动。包括创建设备号、初始化cdev、添加cdev、创建类、创建设备。</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">4.在驱动出口函数中，注销字符设备。</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 115px;"></div><div class="CodeMirror-gutters" style="display: none; height: 115px;"></div></div></div></pre><p>&nbsp;</p><p><strong><span>对代码再理解一下：</span></strong></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//newchrled设备结构体</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">struct</span> <span class="cm-def">newchrled_dev</span>{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">dev_t</span> <span class="cm-variable">devid</span>;<span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 设备号 <span class="cm-tab" role="presentation" cm-text="	"> </span> */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">struct</span> <span class="cm-def">cdev</span> <span class="cm-def">cdev</span>;<span class="cm-tab" role="presentation" cm-text="	">   </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* cdev <span class="cm-tab" role="presentation" cm-text="	">    </span>*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">struct</span> <span class="cm-def">class</span> <span class="cm-operator">*</span><span class="cm-variable">class</span>;<span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 类 <span class="cm-tab" role="presentation" cm-text="	">   </span><span class="cm-tab" role="presentation" cm-text="	">    </span>*/</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">struct</span> <span class="cm-def">device</span> <span class="cm-operator">*</span><span class="cm-variable">device</span>;<span class="cm-tab" role="presentation" cm-text="	">  </span><span class="cm-comment">/* 设备 <span class="cm-tab" role="presentation" cm-text="	">  </span> */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable-3">int</span> <span class="cm-variable">major</span>;<span class="cm-tab" role="presentation" cm-text="	">  </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 主设备号<span class="cm-tab" role="presentation" cm-text="	"> </span>  */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable-3">int</span> <span class="cm-variable">minor</span>;<span class="cm-tab" role="presentation" cm-text="	">  </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 次设备号 &nbsp; */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//定义led设备</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-keyword">struct</span> <span class="cm-def">newchrled_dev</span> <span class="cm-def">newchrled</span>;<span class="cm-tab" role="presentation" cm-text="	"> </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//open函数。要将设备设置成private_data</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable-3">int</span> <span class="cm-def">led_open</span>(<span class="cm-keyword">struct</span> <span class="cm-def">inode</span> <span class="cm-operator">*</span><span class="cm-variable">inode</span>, <span class="cm-keyword">struct</span> <span class="cm-def">file</span> <span class="cm-operator">*</span><span class="cm-variable">filp</span>)</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">filp</span><span class="cm-operator">-&gt;</span><span class="cm-variable">private_data</span> <span class="cm-operator">=</span> <span class="cm-operator">&amp;</span><span class="cm-variable">newchrled</span>; <span class="cm-comment">/* 设置私有数据 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-number">0</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//设备操作函数  多了一个.owner = THIS_MODULE</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-keyword">struct</span> <span class="cm-def">file_operations</span> <span class="cm-def">newchrled_fops</span> <span class="cm-operator">=</span> {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">owner</span> <span class="cm-operator">=</span> <span class="cm-variable">THIS_MODULE</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">open</span> <span class="cm-operator">=</span> <span class="cm-variable">led_open</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">read</span> <span class="cm-operator">=</span> <span class="cm-variable">led_read</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">write</span> <span class="cm-operator">=</span> <span class="cm-variable">led_write</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">release</span> <span class="cm-operator">=</span> <span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-variable">led_release</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//驱动入口函数</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable-3">int</span> <span class="cm-variable">__init</span> <span class="cm-def">led_init</span>(<span class="cm-variable-3">void</span>)</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>......</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 注册字符设备驱动 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 1、创建设备号 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span> (<span class="cm-variable">newchrled</span>.<span class="cm-variable">major</span>) {<span class="cm-tab" role="presentation" cm-text="	">  </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/*  定义了设备号 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">newchrled</span>.<span class="cm-variable">devid</span> <span class="cm-operator">=</span> <span class="cm-variable">MKDEV</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">major</span>, <span class="cm-number">0</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">register_chrdev_region</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">devid</span>, <span class="cm-variable">NEWCHRLED_CNT</span>, <span class="cm-variable">NEWCHRLED_NAME</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>} <span class="cm-keyword">else</span> {<span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 没有定义设备号 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">alloc_chrdev_region</span>(<span class="cm-operator">&amp;</span><span class="cm-variable">newchrled</span>.<span class="cm-variable">devid</span>, <span class="cm-number">0</span>, <span class="cm-variable">NEWCHRLED_CNT</span>, <span class="cm-variable">NEWCHRLED_NAME</span>);<span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 申请设备号 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">newchrled</span>.<span class="cm-variable">major</span> <span class="cm-operator">=</span> <span class="cm-variable">MAJOR</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">devid</span>);<span class="cm-tab" role="presentation" cm-text="	">   </span><span class="cm-comment">/* 获取分配号的主设备号 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">newchrled</span>.<span class="cm-variable">minor</span> <span class="cm-operator">=</span> <span class="cm-variable">MINOR</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">devid</span>);<span class="cm-tab" role="presentation" cm-text="	">   </span><span class="cm-comment">/* 获取分配号的次设备号 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">printk</span>(<span class="cm-string">"newcheled major=%d,minor=%d\r\n"</span>,<span class="cm-variable">newchrled</span>.<span class="cm-variable">major</span>, <span class="cm-variable">newchrled</span>.<span class="cm-variable">minor</span>);<span class="cm-tab" role="presentation" cm-text="	"> </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">// 2、初始化字符设备cdev</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">newchrled</span>.<span class="cm-variable">cdev</span>.<span class="cm-variable">owner</span> <span class="cm-operator">=</span> <span class="cm-variable">THIS_MODULE</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">cdev_init</span>(<span class="cm-operator">&amp;</span><span class="cm-variable">newchrled</span>.<span class="cm-variable">cdev</span>, <span class="cm-operator">&amp;</span><span class="cm-variable">newchrled_fops</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">// 3、添加一个字符设备cdev</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">cdev_add</span>(<span class="cm-operator">&amp;</span><span class="cm-variable">newchrled</span>.<span class="cm-variable">cdev</span>, <span class="cm-variable">newchrled</span>.<span class="cm-variable">devid</span>, <span class="cm-variable">NEWCHRLED_CNT</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">// 4、创建类 </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">newchrled</span>.<span class="cm-variable">class</span> <span class="cm-operator">=</span> <span class="cm-variable">class_create</span>(<span class="cm-variable">THIS_MODULE</span>, <span class="cm-variable">NEWCHRLED_NAME</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span> (<span class="cm-variable">IS_ERR</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">class</span>)) {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-variable">PTR_ERR</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">class</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">// 5、创建设备</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">newchrled</span>.<span class="cm-variable">device</span> <span class="cm-operator">=</span> <span class="cm-variable">device_create</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">class</span>, <span class="cm-variable">NULL</span>, <span class="cm-variable">newchrled</span>.<span class="cm-variable">devid</span>, <span class="cm-variable">NULL</span>, <span class="cm-variable">NEWCHRLED_NAME</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">if</span> (<span class="cm-variable">IS_ERR</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">device</span>)) {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-variable">PTR_ERR</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">device</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" class="cm-tab-wrap-hack" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-keyword">return</span> <span class="cm-number">0</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">//驱动出口函数</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-variable-3">void</span> <span class="cm-variable">__exit</span> <span class="cm-def">led_exit</span>(<span class="cm-variable-3">void</span>)</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">{</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>......</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 注销字符设备驱动 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">cdev_del</span>(<span class="cm-operator">&amp;</span><span class="cm-variable">newchrled</span>.<span class="cm-variable">cdev</span>);<span class="cm-comment">/*  删除cdev */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">unregister_chrdev_region</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">devid</span>, <span class="cm-variable">NEWCHRLED_CNT</span>); <span class="cm-comment">/* 注销设备号 */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">device_destroy</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">class</span>, <span class="cm-variable">newchrled</span>.<span class="cm-variable">devid</span>);<span class="cm-tab" role="presentation" cm-text="	">   </span><span class="cm-comment">//删除设备</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-variable">class_destroy</span>(<span class="cm-variable">newchrled</span>.<span class="cm-variable">class</span>);<span class="cm-tab" role="presentation" cm-text="	"> </span><span class="cm-comment">//删除类</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 1840px;"></div><div class="CodeMirror-gutters" style="display: none; height: 1840px;"></div></div></div></pre><p>&nbsp;</p><h5><a name="2）应用程序-n2165" class="md-header-anchor"></a><span>2）应用程序</span></h5><p><span>和之前的一样就可以了</span></p><p>&nbsp;</p><h4><a name="245-运行测试" class="md-header-anchor"></a><span>2.4.5 运行测试</span></h4><p><span>驱动程序和应用程序，按照之前的方法进行编译。</span></p><p><span>输入以下命令，加载驱动：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang=""><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">depmod</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">modprobe newchrled.ko</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 46px;"></div><div class="CodeMirror-gutters" style="display: none; height: 46px;"></div></div></div></pre><p><span>驱动加载成功以后会输出申请到的主设备号和次设备号。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211739141.png" referrerpolicy="no-referrer" alt="image-20230621173938050"></p><p><span>驱动加载成功以后会自动在/dev 目录下创建设备节点文件/dev/newchrdev。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211740308.png" referrerpolicy="no-referrer" alt="image-20230621174032234"></p><p><span>之后对/dev/newchrdev 这个设备进行驱动即可。</span></p><p>&nbsp;</p><p>&nbsp;</p><h3><a name="25-linux设备树" class="md-header-anchor"></a><span>2.5 linux设备树</span></h3><p><span>在之前的学习笔记里有写，这里就不再赘述，只记录重要的部分。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306211747469.png" referrerpolicy="no-referrer" alt="image-20230621174745397"></p><h4><a name="251-什么是设备树" class="md-header-anchor"></a><span>2.5.1 什么是设备树</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301045399.png" referrerpolicy="no-referrer" alt="image-20230630104521262"></p><p><span>dtsi是头文件，描述SOC信息；dts是源文件，描述板子信息。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301047082.png" referrerpolicy="no-referrer" alt="image-20230630104738015"></p><p>&nbsp;</p><h4><a name="252-dtb和dts" class="md-header-anchor"></a><span>2.5.2 dtb和dts</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301059745.png" referrerpolicy="no-referrer" alt="image-20230630105922683"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301101601.png" referrerpolicy="no-referrer" alt="image-20230630110131524"></p><p><span>...此处略去一些板子的配置...</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301101867.png" referrerpolicy="no-referrer" alt="image-20230630110157791"></p><p>&nbsp;</p><h4><a name="253-设备树语法" class="md-header-anchor"></a><span>2.5.3 设备树语法</span></h4><h5><a name="1）dtsi头文件" class="md-header-anchor"></a><span>1）.dtsi头文件</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301113806.png" referrerpolicy="no-referrer" alt="image-20230630111337741"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301114248.png" referrerpolicy="no-referrer" alt="image-20230630111412168"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301114376.png" referrerpolicy="no-referrer" alt="image-20230630111430294"></p><p>&nbsp;</p><h5><a name="2）设备节点" class="md-header-anchor"></a><span>2）设备节点</span></h5><p><span>每个设备都是一个节点，叫做设备节点，每个节点都通过一些属性信息来描述节点信息，属性就是键—值对。</span></p><p><span>以下是从imx6ull.dtsi 文件中缩减出来的设备树文件内容：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301153894.png" referrerpolicy="no-referrer" alt="image-20230630115336810"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301155862.png" referrerpolicy="no-referrer" alt="image-20230630115558789"></p><p>&nbsp;</p><h4><a name="254-标准属性" class="md-header-anchor"></a><span>2.5.4 标准属性</span></h4><h5><a name="1）compatible属性" class="md-header-anchor"></a><span>1）compatible属性</span></h5><p><span>该属性是用于匹配设备节点和设备驱动的。“compatible”表示“兼容”。</span></p><p><span>对于某个LED，内核中可能有A、B、C三个驱动都支持它，可以这样写：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="C++"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c++"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">led</span> {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">compatible</span> <span class="cm-operator">=</span> <span class="cm-variable">“A”</span>, <span class="cm-variable">“B”</span>, <span class="cm-variable">“C”</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 69px;"></div><div class="CodeMirror-gutters" style="display: none; height: 69px;"></div></div></div></pre><p><span>内核启动时，就会为这个LED按这样的优先顺序为它找到驱动程序：A、B、C。</span></p><p><span>compatible 属性的值是一个</span><strong><span>字符串列表</span></strong><span>， compatible 属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序， compatible 属性的值格式如下所示：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="C++"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c++"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-string">"manufacturer,model"</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">其中</span> <span class="cm-variable">manufacturer</span> <span class="cm-variable">表示厂商，</span> <span class="cm-variable">model</span> <span class="cm-variable">一般是模块对应的驱动名字。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">比如</span> <span class="cm-variable">imx6ull</span><span class="cm-operator">-</span><span class="cm-variable">alientekemmc</span>.<span class="cm-variable">dts</span> <span class="cm-variable">中</span> <span class="cm-variable">sound</span> <span class="cm-variable">节点是</span> <span class="cm-variable">I</span>.<span class="cm-variable">MX6U</span><span class="cm-operator">-</span><span class="cm-variable">ALPHA</span> <span class="cm-variable">开发的音频设备节点，</span> </span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">I</span>.<span class="cm-variable">MX6U</span><span class="cm-operator">-</span><span class="cm-variable">ALPHA</span> <span class="cm-def">开发板上的音频芯片采用的欧胜</span>(<span class="cm-variable">WOLFSON</span>)<span class="cm-variable">出品的</span> <span class="cm-variable">WM8960，</span> </span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">sound</span> <span class="cm-variable">节点的</span> <span class="cm-variable">compatible</span> <span class="cm-variable">属性值如下：</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">compatible</span> <span class="cm-operator">=</span> <span class="cm-string">"fsl,imx6ul-evk-wm8960"</span>,<span class="cm-string">"fsl,imx-audio-wm8960"</span>;</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 184px;"></div><div class="CodeMirror-gutters" style="display: none; height: 184px;"></div></div></div></pre><p><span>属性值有两个，分别为“fsl,imx6ul-evk-wm8960”和“fsl,imx-audio-wm8960”，其中“fsl”表示厂商是飞思卡尔，“imx6ul-evk-wm8960”和“imx-audio-wm8960”表示驱动模块名字。 sound这个设备首先使用第一个兼容值在 Linux 内核里面查找，看看能不能找到与之匹配的驱动文件，如果没有找到的话就使用第二个兼容值查。</span></p><p><span>一般驱动程序文件都会有一个 OF 匹配表，此 OF 匹配表保存着一些 compatible 值，如果设备节点的 compatible 属性值和 OF 匹配表中的任何一个值相等，那么就表示设备可以使用这个驱动。比如在文件 imx-wm8960.c 中有如下内容：</span></p><p><span>【在设备树中的compatible需要与驱动代码.compatible所匹配】</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301159672.png" referrerpolicy="no-referrer" alt="img"></p><p><span>根节点下也有compatible属性，用来选择哪一个“machine desc”：一个内核可以支持machine A，也支持machine B，内核启动后会根据根节点的compatible属性找到对应的machine desc结构体，执行其中的初始化函数。</span></p><p><span>compatible的值，建议取这样的形式：&quot;manufacturer,model&quot;，即“厂家名,模块名”。</span></p><p><span>比如：compatible = &quot;fsl,imx6ull-gpmi-nand&quot;, &quot;fsl, imx6ul-gpmi-nand&quot;;</span></p><p><strong><span>注意</span></strong><span>：machine desc的意思就是“机器描述”，学到内核启动流程时才涉及。</span></p><p>&nbsp;</p><h5><a name="2）model属性" class="md-header-anchor"></a><span>2）model属性</span></h5><p><span>model 属性值也是一个字符串列表，一般 model 属性描述设备模块信息，比如名字什么的。</span></p><p><span>compatible属性是一个字符串列表，表示可以你的硬件兼容A、B、C等驱动；model用来准确地定义这个硬件是什么。即：从compatible属性中可以知道它兼容哪些板，但是它到底是什么板？用model属性来明确。</span></p><p><span>例如：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="C++"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c++"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-operator">/</span> {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-variable">compatible</span> <span class="cm-operator">=</span> <span class="cm-string">"samsung,smdk2440"</span>, <span class="cm-string">"samsung,mini2440"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-variable">model</span> <span class="cm-operator">=</span> <span class="cm-string">"jz2440_v3"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 92px;"></div><div class="CodeMirror-gutters" style="display: none; height: 92px;"></div></div></div></pre><p><span>它表示&quot;jz2440_v3&quot;这个单板，可以兼容内核中的“smdk2440”，也兼容“mini2440”。</span></p><p>&nbsp;</p><h5><a name="3）status属性" class="md-header-anchor"></a><span>3）status属性</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301201663.png" referrerpolicy="no-referrer" alt="image-20230630120140567"></p><p>&nbsp;</p><h5><a name="4）address-cells-和-size-cells-属性" class="md-header-anchor"></a><span>4）address-cells 和 size-cells 属性</span></h5><p><span>cell指一个32位的数值，</span></p><p><strong><span>address-cells</span></strong><span>：address要用多少个32位数来表示，属性值决定了子节点 reg 属性中地址信息所占用的字长(32 位)；</span></p><p><strong><span>size-cells</span></strong><span>：size要用多少个32位数来表示，属性值决定了子节点 reg 属性中长度信息所占的字长(32 位)。</span></p><p><span>比如一段内存，怎么描述它的起始地址和大小？</span></p><p><span>#</span><span>address-cells 和#size-cells 表明了子节点应该如何编写 reg 属性值，一般 reg 属性都是和地址有关的内容，和地址相关的信息有两种：起始地址和地址长度， reg 属性的格式一为：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="C++"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c++"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">reg</span> <span class="cm-operator">=</span> <span class="cm-operator">&lt;</span><span class="cm-variable">address1</span> <span class="cm-variable">length1</span> <span class="cm-variable">address2</span> <span class="cm-variable">length2</span> <span class="cm-variable">address3</span> <span class="cm-variable">length3……</span><span class="cm-operator">&gt;</span></span></pre></div></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 23px;"></div><div class="CodeMirror-gutters" style="display: none; height: 23px;"></div></div></div></pre><p><span>每个“address length”组合表示一个地址范围，其中 address 是起始地址， length 是地址长度， #address-cells 表明 address 这个数据所占用的字长， #size-cells 表明 length 这个数据所占用的字长，比如:</span></p><ul><li><strong><span>例1</span></strong></li></ul><p><span>下例中，address-cells为1，所以reg中用1个数来表示地址，即用0x80000000来表示地址；size-cells为1，所以reg中用1个数来表示大小，即用0x20000000表示大小：</span></p><p><span>起始地址是0x80000000，地址长度为0x20000000</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="C++"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c++"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-operator">/</span> {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#address-cells = &lt;1&gt;;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-meta">#size-cells = &lt;1&gt;;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">memory</span> {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">reg</span> <span class="cm-operator">=</span> <span class="cm-operator">&lt;</span><span class="cm-number">0x80000000</span> <span class="cm-number">0x20000000</span><span class="cm-operator">&gt;</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  };</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 161px;"></div><div class="CodeMirror-gutters" style="display: none; height: 161px;"></div></div></div></pre><ul><li><strong><span>例2</span></strong></li></ul><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="C++" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c++"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">spi4</span> {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-variable">compatible</span> <span class="cm-operator">=</span> <span class="cm-string">"spi-gpio"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-meta">#address-cells = &lt;1&gt;;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-meta">#size-cells = &lt;0&gt;;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">gpio_spi</span>: <span class="cm-variable">gpio_spi@0</span> {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-variable">compatible</span> <span class="cm-operator">=</span> <span class="cm-string">"fairchild,74hc595"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-variable">reg</span> <span class="cm-operator">=</span> <span class="cm-operator">&lt;</span><span class="cm-number">0</span><span class="cm-operator">&gt;</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; };</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> };</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-variable">aips3</span>: <span class="cm-variable">aips</span><span class="cm-operator">-</span><span class="cm-variable">bus@02200000</span> {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-variable">compatible</span> <span class="cm-operator">=</span> <span class="cm-string">"fsl,aips-bus"</span>, <span class="cm-string">"simple-bus"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-meta">#address-cells = &lt;1&gt;;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-meta">#size-cells = &lt;1&gt;;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> <span class="cm-variable">dcp</span>: <span class="cm-variable">dcp@02280000</span> {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-variable">compatible</span> <span class="cm-operator">=</span> <span class="cm-string">"fsl,imx6sl-dcp"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-variable">reg</span> <span class="cm-operator">=</span> <span class="cm-operator">&lt;</span><span class="cm-number">0x02280000</span> <span class="cm-number">0x4000</span><span class="cm-operator">&gt;</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; };</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> };</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 483px;"></div><div class="CodeMirror-gutters" style="display: none; height: 483px;"></div></div></div></pre><p><span>第 3， 4 行，节点 spi4 的#address-cells = &lt;1&gt;， #size-cells = &lt;0&gt;，说明 spi4 的子节点 reg 属性中起始地址所占用的字长为 1，地址长度所占用的字长为 0。</span></p><p><span>第 8 行，</span><strong><span>子节点 gpio_spi</span></strong><span>: gpio_spi@0 的 reg 属性值为 &lt;0&gt;，因为父节点设置了#addresscells = &lt;1&gt;， #size-cells = &lt;0&gt;，</span><strong><span>因此 addres=0没有 length 的值，相当于设置了起始地址，而没有设置地址长度</span></strong><span>。</span></p><p><span>第 14， 15 行，设置 aips3: aips-bus@02200000 节点#address-cells = &lt;1&gt;， #size-cells = &lt;1&gt;，说明 aips3: aips-bus@02200000 节点起始地址长度所占用的字长为 1，地址长度所占用的字长也为 1。</span></p><p><span>第 19 行，子节点 dcp: dcp@02280000 的 reg 属性值为&lt;0x02280000 0x4000&gt;，因为父节点设置了#address-cells = &lt;1&gt;， #size-cells = &lt;1&gt;， address= 0x02280000， length= 0x4000，</span><strong><span>相当于设置了起始地址为 0x02280000，地址长度为 0x40000。</span></strong></p><p>&nbsp;</p><h5><a name="5）reg属性" class="md-header-anchor"></a><span>5）reg属性</span></h5><p><span>reg 属性前面已经提到过了， reg 属性的值一般是(address， length)对。 reg 属性一般用于描述设备地址空间资源信息，一般都是某个外设的寄存器地址范围信息，比如在 imx6ull.dtsi 中有如下内容:</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="SQL"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="sql"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">uart1: serial@02020000 {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; compatible = <span class="cm-string">"fsl,imx6ul-uart"</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; <span class="cm-string">"fsl,imx6q-uart"</span>, <span class="cm-string">"fsl,imx21-uart"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; reg = &lt;<span class="cm-number">0x02020000</span> <span class="cm-number">0x4000</span>&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; interrupts = &lt;GIC_SPI <span class="cm-number">26</span> IRQ_TYPE_LEVEL_HIGH&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; clocks = &lt;&amp;clks IMX6UL_CLK_UART1_IPG&gt;,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; &lt;&amp;clks IMX6UL_CLK_UART1_SERIAL&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; clock-names = <span class="cm-string">"ipg"</span>, <span class="cm-string">"per"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; status = <span class="cm-string">"disabled"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> };</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 230px;"></div><div class="CodeMirror-gutters" style="display: none; height: 230px;"></div></div></div></pre><p><span>上述代码是节点 uart1， uart1 节点描述了 I.MX6ULL 的 UART1 相关信息，</span><strong><span>重点是第4行的 reg 属性</span></strong><span>。其中 uart1 的父节点 aips1: aips-bus@02000000 设置了#address-cells = &lt;1&gt;、 #sizecells = &lt;1&gt;，因此 reg 属性中 address=0x02020000， length=0x4000。查阅《I.MX6ULL 参考手册》可知， I.MX6ULL 的 UART1 寄存器首地址为 0x02020000，但是 UART1 的地址长度(范围)并没有 0x4000 这么多，这里我们重点是获取 UART1 寄存器首地址。</span></p><p>&nbsp;</p><p><strong><span>例子补充：</span></strong></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c++" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c++"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">alphaled</span> {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-meta">#address-cells = &lt;1&gt;;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-meta">#size-cells = &lt;1&gt;;</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-variable">compatible</span> <span class="cm-operator">=</span> <span class="cm-string">"atkalpha-led"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-variable">status</span> <span class="cm-operator">=</span> <span class="cm-string">"okay"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;<span class="cm-variable">reg</span> <span class="cm-operator">=</span> <span class="cm-operator">&lt;</span> <span class="cm-number">0X020C406C</span> <span class="cm-number">0X04</span> <span class="cm-comment">/* CCM_CCGR1_BASE */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-number">0X020E0068</span> <span class="cm-number">0X04</span> <span class="cm-comment">/* SW_MUX_GPIO1_IO03_BASE */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-number">0X020E02F4</span> <span class="cm-number">0X04</span> <span class="cm-comment">/* SW_PAD_GPIO1_IO03_BASE */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-number">0X0209C000</span> <span class="cm-number">0X04</span> <span class="cm-comment">/* GPIO1_DR_BASE */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-number">0X0209C004</span> <span class="cm-number">0X04</span> <span class="cm-operator">&gt;</span>; <span class="cm-comment">/* GPIO1_GDIR_BASE */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">以第一对地址和大小为例：</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-number">0X020C406C</span> <span class="cm-number">0X04</span> <span class="cm-comment">/* CCM_CCGR1_BASE */</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">其中，0X020C406C</span> <span class="cm-variable">是设备节点的物理地址（也可以是虚拟地址），表示</span> <span class="cm-variable">CCM_CCGR1_BASE。0X04</span> <span class="cm-variable">是该地址所占的大小（单位为字节），表示地址范围的长度为</span> <span class="cm-number">4</span> <span class="cm-variable">字节。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">同样的方式，后续的地址和大小也表示了其他相关寄存器或资源的信息。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">例如，0X020E0068</span> <span class="cm-number">0X04</span> <span class="cm-variable">表示</span> <span class="cm-variable">SW_MUX_GPIO1_IO03_BASE</span> <span class="cm-variable">的地址和大小，0X020E02F4</span> <span class="cm-number">0X04</span> <span class="cm-variable">表示</span> <span class="cm-variable">SW_PAD_GPIO1_IO03_BASE</span> <span class="cm-variable">的地址和大小，依此类推。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">这样，通过</span> <span class="cm-variable">reg</span> <span class="cm-variable">属性，设备树描述了输入输出引脚、寄存器等在地址空间中的位置和大小，从而在内核初始化时可以正确配置和管理这些资源。同时，注释形式的文字说明也提供了对每个地址和对应资源的描述，以便更好地理解和使用设备树。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">请注意，在编写设备树时，应确保地址和大小的数值正确，并根据具体硬件和驱动程序的要求来设置</span></span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 552px;"></div><div class="CodeMirror-gutters" style="display: none; height: 552px;"></div></div></div></pre><p>&nbsp;</p><h5><a name="6）range属性" class="md-header-anchor"></a><span>6）range属性</span></h5><p><span>ranges属性值可以为空或者按照(child-bus-address,parent-bus-address,length)格式编写的数字矩阵， ranges 是一个地址映射/转换表， ranges 属性每个项目由子地址、父地址和地址空间长度这三部分组成：</span></p><p><strong><span>child-bus-address</span></strong><span>：子总线地址空间的物理地址，由父节点的#address-cells 确定此物理地址所占用的字长。</span></p><p><strong><span>parent-bus-address</span></strong><span>： 父总线地址空间的物理地址，同样由父节点的#address-cells 确定此物理地址所占用的字长。</span></p><p><strong><span>length</span></strong><span>： 子地址空间的长度，由父节点的#size-cells 确定此地址长度所占用的字长。</span></p><p><span>如果 ranges 属性值为空值，说明子地址空间和父地址空间完全相同，不需要进行地址转换，对于我们所使用的 I.MX6ULL 来说，子地址空间和父地址空间完全相同，因此会在 imx6ull.dtsi中找到大量的值为空的 ranges 属性，如下所示：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="SQL" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="sql"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">soc {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  compatible = <span class="cm-string">"simple-bus"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  #address-cells = &lt;<span class="cm-number">1</span>&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  #size-cells = &lt;<span class="cm-number">1</span>&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  ranges = &lt;<span class="cm-number">0x0</span> <span class="cm-number">0xe0000000</span> <span class="cm-number">0x00100000</span>&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">serial {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  device_type = <span class="cm-string">"serial"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  compatible = <span class="cm-string">"ns16550"</span>;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  reg = &lt;<span class="cm-number">0x4600</span> <span class="cm-number">0x100</span>&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  clock-frequency = &lt;<span class="cm-number">0</span>&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  interrupts = &lt;<span class="cm-number">0xA</span> <span class="cm-number">0x8</span>&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  interrupt-parent = &lt;&amp;ipic&gt;;</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  };</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 345px;"></div><div class="CodeMirror-gutters" style="display: none; height: 345px;"></div></div></div></pre><p><span>第 6 行定义了 ranges 属性，但是 ranges 属性值为空。</span></p><p><span>第 5 行，节点 soc 定义的 ranges 属性，值为&lt;0x0 0xe0000000 0x00100000&gt;，此属性值指定了一个 1024KB(0x00100000)的地址范围，子地址空间的物理起始地址为 0x0，</span><strong><span>父地址空间的物理起始地址为 0xe0000000</span></strong><span>。</span></p><p><span>第 10 行， serial 是串口设备节点， reg 属性定义了 serial 设备寄存器的起始地址为 0x4600，寄存器长度为 0x100。经过地址转换， serial 设备可以从 0xe0004600 开始进行读写操作，0xe0004600=0x4600+0xe0000000。</span></p><p>&nbsp;</p><h5><a name="7）name和devicetype属性" class="md-header-anchor"></a><span>7）name和device_type属性</span></h5><p><span>属性值为字符串，用于记录属性。该属性已经被弃用。</span></p><p><span>以上几个，基本就是标准属性的全部内容。</span></p><p>&nbsp;</p><h4><a name="255-根节点属性" class="md-header-anchor"></a><span>2.5.5 根节点属性</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301212322.png" referrerpolicy="no-referrer" alt="image-20230630121202248"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301212252.png" referrerpolicy="no-referrer" alt="image-20230630121212179"></p><p>&nbsp;</p><h5><a name="使用设备树后的匹配方法" class="md-header-anchor"></a><span>使用设备树后的匹配方法</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301216362.png" referrerpolicy="no-referrer" alt="image-20230630121610292"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301216328.png" referrerpolicy="no-referrer" alt="image-20230630121649240"></p><p><strong><span>我的理解：</span></strong></p><p><span>在DT_MACHINE_START中设置.dt_compat属性指向imx6ul_dt_compat，里面存了字符串，也就是兼容值。如果与根节点中的compatible属性的值匹配，就可以正常启动linux内核。</span></p><p>&nbsp;</p><p><span>linux内核对应的machine_desc：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301226640.png" referrerpolicy="no-referrer" alt="image-20230630122618550"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301226628.png" referrerpolicy="no-referrer" alt="image-20230630122659538"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301227438.png" referrerpolicy="no-referrer" alt="image-20230630122749360"></p><p><strong><span>我的理解：</span></strong></p><p><span>linux内核调用start_kernel函数来启动内核，</span></p><p><span>start_kernel函数调用setup_arch函数来匹配machine_desc，</span></p><p><span>setup_arch函数调用setup_machine_fdt函数来获取匹配的machine_desc，</span></p><p><span>setup_machine_fdt调用of_flat_dt_match_machine函数来获取匹配的machine_desc</span></p><p>&nbsp;</p><h4><a name="256-向节点追加或修改内容" class="md-header-anchor"></a><span>2.5.6 向节点追加或修改内容</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301235419.png" referrerpolicy="no-referrer" alt="image-20230630123514341"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301236507.png" referrerpolicy="no-referrer" alt="image-20230630123641418"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301237060.png" referrerpolicy="no-referrer" alt="image-20230630123704979"></p><p>&nbsp;</p><h4><a name="257-创建小型模板设备树" class="md-header-anchor"></a><span>2.5.7 创建小型模板设备树</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301553852.png" referrerpolicy="no-referrer" alt="image-20230630155353765"></p><p>&nbsp;</p><p><strong><span>步骤如下：</span></strong></p><p><span>添加cpus节点，添加soc节点，添加ocram节点，添加aips1、aips2 和 aips3 这三个子节点，再添加几个控制器，其中 ecspi1 属于 aips1 的子节点，usbotg1 属于 aips2 的子节点，rngb 属于 aips3 的子节点。详细步骤如下：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301632380.png" referrerpolicy="no-referrer" alt="image-20230630163217311"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301631698.png" referrerpolicy="no-referrer" alt="image-20230630163154602"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202306301633619.png" referrerpolicy="no-referrer" alt="image-20230630163313532"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052015840.png" referrerpolicy="no-referrer" alt="image-20230705201541718"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052016143.png" referrerpolicy="no-referrer" alt="image-20230705201609062"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052017005.png" referrerpolicy="no-referrer" alt="image-20230705201706906"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052017636.png" referrerpolicy="no-referrer" alt="image-20230705201720564"></p><p>&nbsp;</p><h4><a name="258-设备树在系统中的体现" class="md-header-anchor"></a><span>2.5.8 设备树在系统中的体现</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052035951.png" referrerpolicy="no-referrer" alt="image-20230705203550877"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052036146.png" referrerpolicy="no-referrer" alt="image-20230705203614054"></p><p>&nbsp;</p><h4><a name="259-特殊节点" class="md-header-anchor"></a><span>2.5.9 特殊节点</span></h4><h5><a name="1）aliases节点" class="md-header-anchor"></a><span>1）aliases节点</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052041066.png" referrerpolicy="no-referrer" alt="image-20230705204102996"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052041680.png" referrerpolicy="no-referrer" alt="image-20230705204115609"></p><p>&nbsp;</p><h5><a name="2）chosen节点" class="md-header-anchor"></a><span>2）chosen节点</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052042643.png" referrerpolicy="no-referrer" alt="image-20230705204243559"></p><p><span>chosen节点添加bootarg属性的步骤：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052048470.png" referrerpolicy="no-referrer" alt="image-20230705204800379"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052048797.png" referrerpolicy="no-referrer" alt="image-20230705204841713"></p><p><strong><span>我的理解：</span></strong></p><p><span>执行bootz命令后，会执行do_bootz()函数，再调用do_bottom_states函数，再调用boot_selected_os函数，再调用boot_fn函数，再调用boot_prep_linux函数来做一些启动Linux之前的准备工作，再调用image_setup_linux函数，再调用image_setup_libfdt函数，再调用fdt_chosen函数在chosen节点中添加bootarg属性。</span></p><p>&nbsp;</p><h4><a name="2510-linux内核解析dtb文件" class="md-header-anchor"></a><span>2.5.10 Linux内核解析DTB文件</span></h4><p><span>Linux 内核在启动的时候会解析 DTB 文件，然后在/proc/device-tree 目录下生成相应的设备树节点文件。接下来我们简单分析一下 Linux 内核是如何解析 DTB 文件的，流程如图 43.7.1 所示：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052056540.png" referrerpolicy="no-referrer" alt="image-20230705205600471"></p><p><span>在 start_kernel 函数中完成了设备树节点解析的工作，最终实际工作的函数为 unflatten_dt_node。</span></p><p>&nbsp;</p><h4><a name="2511-绑定信息文档" class="md-header-anchor"></a><span>2.5.11 绑定信息文档</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052057735.png" referrerpolicy="no-referrer" alt="image-20230705205724649"></p><p>&nbsp;</p><h4><a name="2512-设备树常用的of操作函数" class="md-header-anchor"></a><span>2.5.12 设备树常用的of操作函数</span></h4><h5><a name="1）查找节点有关" class="md-header-anchor"></a><span>1）查找节点有关</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052102960.png" referrerpolicy="no-referrer" alt="image-20230705210233872"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052103083.png" referrerpolicy="no-referrer" alt="image-20230705210340996"></p><p>&nbsp;</p><h5><a name="2）查找父子节点" class="md-header-anchor"></a><span>2）查找父/子节点</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052107992.png" referrerpolicy="no-referrer" alt="image-20230705210740923"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052107734.png" referrerpolicy="no-referrer" alt="image-20230705210754662"></p><p>&nbsp;</p><h5><a name="3）提取属性值" class="md-header-anchor"></a><span>3）提取属性值</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052110037.png" referrerpolicy="no-referrer" alt="image-20230705211003950"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052111503.png" referrerpolicy="no-referrer" alt="image-20230705211147411"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052112414.png" referrerpolicy="no-referrer" alt="image-20230705211228323"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052113265.png" referrerpolicy="no-referrer" alt="image-20230705211300193"></p><p>&nbsp;</p><h5><a name="4）其它常用的of函数" class="md-header-anchor"></a><span>4）其它常用的of函数</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052114049.png" referrerpolicy="no-referrer" alt="image-20230705211427970"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052115611.png" referrerpolicy="no-referrer" alt="image-20230705211522524"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052117691.png" referrerpolicy="no-referrer" alt="image-20230705211735607"></p><p><span>这里的</span><code>of_iomap</code><span> 函数的作用是根据设备树节点中的 </span><code>reg</code><span> 属性信息，将 I/O 地址范围映射到内核的虚拟地址空间，并返回映射后的内核虚拟地址。</span></p><p><span>例如：</span><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091408439.png" referrerpolicy="no-referrer" alt="image-20230709140855318"></p><p>&nbsp;</p><h3><a name="26-设备树下的led驱动实验" class="md-header-anchor"></a><span>2.6 设备树下的LED驱动实验</span></h3><h4><a name="261-修改设备树文件" class="md-header-anchor"></a><span>2.6.1 修改设备树文件</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052134393.png" referrerpolicy="no-referrer" alt="image-20230705213449315"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052135874.png" referrerpolicy="no-referrer" alt="image-20230705213506776"></p><p>&nbsp;</p><p>&nbsp;</p><h4><a name="262-led驱动程序编写" class="md-header-anchor"></a><span>2.6.2 LED驱动程序编写</span></h4><p><span>与2.4中的新字符设备驱动相比，区别主要在于：</span></p><ol start='' ><li><span>设备结构体 struct dtsled_dev 中，多了一个设备节点 struct device_node *nd</span></li><li><span>驱动入口函数中，使用of操作函数来获取设备树的一些内容</span></li><li><span>寄存器地址映射也改用of_iomap函数</span></li></ol><p><span>以下是驱动程序的部分内容，只列出了修改后的部分。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052148873.png" referrerpolicy="no-referrer" alt="image-20230705214822793"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052148094.png" referrerpolicy="no-referrer" alt="image-20230705214846006"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052149403.png" referrerpolicy="no-referrer" alt="image-20230705214905322"></p><p>&nbsp;</p><p><span>正点原子文档是这么说的：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052203800.png" referrerpolicy="no-referrer" alt="image-20230705220339719"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307052203821.png" referrerpolicy="no-referrer" alt="image-20230705220348746"></p><p>&nbsp;</p><h4><a name="263-应用程序编写" class="md-header-anchor"></a><span>2.6.3 应用程序编写</span></h4><p><span>和前面的一样，直接用就行。</span></p><p>&nbsp;</p><h4><a name="264-运行测试" class="md-header-anchor"></a><span>2.6.4 运行测试</span></h4><h5><a name="1）编译" class="md-header-anchor"></a><span>1）编译</span></h5><p><span>首先，修改完设备树后，需要重新编译设备树。由于编译器的缓存导致编译，可以尝试清除编译器缓存并重新编译驱动程序，以避免重新编译整个内核。</span></p><p><span>即先make clean，再make dtbs。</span></p><p><span>编译驱动程序和应用程序都和前面一样就行。</span></p><h5><a name="2）运行" class="md-header-anchor"></a><span>2）运行</span></h5><p><span>编译出来的dtsled.ko和ledApp这两个文件，还是放到根目录的/lib/modules/4.1.15目录中。</span></p><p><span>还是使用depmod 和 modprobe dstled.ko 这两个命令，之后/dev/dtsled这个设备就已经创建成功，可以对它操作。</span></p><p><span>可以看到，alphaled节点被成功创建：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091356239.png" referrerpolicy="no-referrer" alt="image-20230709135639044"></p><p>&nbsp;</p><h3><a name="27-pinctrl-和-gpio-子系统实验" class="md-header-anchor"></a><span>2.7 pinctrl 和 gpio 子系统实验</span></h3><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091412103.png" referrerpolicy="no-referrer" alt="image-20230709141239013"></p><h4><a name="271-pinctrl子系统简介" class="md-header-anchor"></a><span>2.7.1 pinctrl子系统简介</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091413415.png" referrerpolicy="no-referrer" alt="image-20230709141302327"></p><p>&nbsp;</p><h4><a name="272-pinctrl子系统驱动" class="md-header-anchor"></a><span>2.7.2 pinctrl子系统驱动</span></h4><h5><a name="1）配置" class="md-header-anchor"></a><span>1）配置</span></h5><p><span>打开 imx6ull.dtsi 文件，找到一个叫做 iomuxc 的节点，iomuxc 节点就是 I.MX6ULL 的 IOMUXC 外设对应的节点。在dtsi文件中，这个节点的内容很少，主要是在dts文件中追加的。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091421644.png" referrerpolicy="no-referrer" alt="image-20230709142157531"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091424967.png" referrerpolicy="no-referrer" alt="image-20230709142436861"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091425092.png" referrerpolicy="no-referrer" alt="image-20230709142555985"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091426024.png" referrerpolicy="no-referrer" alt="image-20230709142657927"></p><p>&nbsp;</p><h5><a name="2）pin驱动程序" class="md-header-anchor"></a><span>2）PIN驱动程序</span></h5><p><span>这部分暂时先不深入了解了。</span></p><p><span>补充：这里的imx_pinctrl_info的定义为：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation"><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-keyword">struct</span> <span class="cm-def">imx_pinctrl_soc_info</span> <span class="cm-def">imx6ul_pinctrl_info</span> <span class="cm-operator">=</span> {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">pins</span> <span class="cm-operator">=</span> <span class="cm-variable">imx6ul_pinctrl_pads</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">npins</span> <span class="cm-operator">=</span> <span class="cm-variable">ARRAY_SIZE</span>(<span class="cm-variable">imx6ul_pinctrl_pads</span>),</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 92px;"></div><div class="CodeMirror-gutters" style="display: none; height: 92px;"></div></div></div></pre><p>&nbsp;</p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091450136.png" referrerpolicy="no-referrer" alt="image-20230709145049043"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091451051.png" referrerpolicy="no-referrer" alt="image-20230709145137941"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091453634.png" referrerpolicy="no-referrer" alt="image-20230709145354530"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091454913.png" referrerpolicy="no-referrer" alt="image-20230709145446804"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091455858.png" referrerpolicy="no-referrer" alt="image-20230709145529744"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091456633.png" referrerpolicy="no-referrer" alt="image-20230709145613547"></p><p>&nbsp;</p><h5><a name="3）设备树中添加pinctrl节点模板" class="md-header-anchor"></a><span>3）设备树中添加pinctrl节点模板</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091516820.png" referrerpolicy="no-referrer" alt="image-20230709151632715"></p><p>&nbsp;</p><h4><a name="273-gpio子系统简介" class="md-header-anchor"></a><span>2.7.3 gpio子系统简介</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091517242.png" referrerpolicy="no-referrer" alt="image-20230709151745152"></p><p>&nbsp;</p><h4><a name="274-gpio子系统驱动" class="md-header-anchor"></a><span>2.7.4 gpio子系统驱动</span></h4><h5><a name="1）设备中的gpio信息" class="md-header-anchor"></a><span>1）设备中的gpio信息</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091519947.png" referrerpolicy="no-referrer" alt="image-20230709151945846"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091521785.png" referrerpolicy="no-referrer" alt="image-20230709152154667"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091524633.png" referrerpolicy="no-referrer" alt="image-20230709152412536"></p><p>&nbsp;</p><h5><a name="2）gpio驱动程序" class="md-header-anchor"></a><span>2）gpio驱动程序</span></h5><p><span>暂时了解即可</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091526425.png" referrerpolicy="no-referrer" alt="image-20230709152610327"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091526258.png" referrerpolicy="no-referrer" alt="image-20230709152657149"></p><p><span>... 代码先省略了，正点原子的教程里有 ...</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091528761.png" referrerpolicy="no-referrer" alt="image-20230709152840658"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091529557.png" referrerpolicy="no-referrer" alt="image-20230709152949447"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091530959.png" referrerpolicy="no-referrer" alt="image-20230709153042856"></p><p>&nbsp;</p><h5><a name="3）gpio子系统api函数" class="md-header-anchor"></a><span>3）gpio子系统API函数</span></h5><p><span>平时的开发，一般会用这些函数就可以了。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091533836.png" referrerpolicy="no-referrer" alt="image-20230709153306723"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091533069.png" referrerpolicy="no-referrer" alt="image-20230709153336976"></p><p>&nbsp;</p><h5><a name="4）设备树中添加gpio节点模板" class="md-header-anchor"></a><span>4）设备树中添加gpio节点模板</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091535307.png" referrerpolicy="no-referrer" alt="image-20230709153524209"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091554215.png" referrerpolicy="no-referrer" alt="image-20230709155406121"></p><p>&nbsp;</p><p>&nbsp;</p><h4><a name="275-gpio相关的of操作函数" class="md-header-anchor"></a><span>2.7.5 gpio相关的of操作函数</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091603875.png" referrerpolicy="no-referrer" alt="image-20230709160339752"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091604913.png" referrerpolicy="no-referrer" alt="image-20230709160415823"></p><p>&nbsp;</p><h4><a name="276-实验程序编写" class="md-header-anchor"></a><span>2.7.6 实验程序编写</span></h4><h5><a name="1）修改设备树文件" class="md-header-anchor"></a><span>1）修改设备树文件</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091607581.png" referrerpolicy="no-referrer" alt="image-20230709160758482"></p><p><span>pinctrl : ledgrp中，前者是标识符，后者是属性。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091609398.png" referrerpolicy="no-referrer" alt="image-20230709160915285"></p><p><strong><span>我的理解：</span></strong></p><p><span>前面那个MX6UL_PAD_GPIO1_IO3_GPIO1_IO03算是PIN的配置；后面那个gpio1 3算是gpio的配置，都要屏蔽掉·。</span></p><p>&nbsp;</p><p><span>修改完成后的dts文件如图：</span></p><p><span>在imx6ul-evk节点中添加一个pinctrl_led子节点</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091628057.png" referrerpolicy="no-referrer" alt="image-20230709162831965"></p><p><span>在/下添加一个gpioled子节点</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091631237.png" referrerpolicy="no-referrer" alt="image-20230709163141142"></p><p>&nbsp;</p><p><span>修改完成之后，还是make clean + make dtbs来编译新的设备树。</span></p><p>&nbsp;</p><h5><a name="2）驱动程序" class="md-header-anchor"></a><span>2）驱动程序</span></h5><p><span>这里只节选了部分，完整的可以正点原子教程。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091643995.png" referrerpolicy="no-referrer" alt="image-20230709164357891"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091645451.png" referrerpolicy="no-referrer" alt="image-20230709164525350"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091646053.png" referrerpolicy="no-referrer" alt="image-20230709164655953"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091647353.png" referrerpolicy="no-referrer" alt="image-20230709164741262"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091648061.png" referrerpolicy="no-referrer" alt="image-20230709164812965"></p><p>&nbsp;</p><p><span>我的理解：</span></p><p><span>在定义设备时，多了一个int来记录LED所使用的gpio编号。</span></p><p><span>在写函数里，不直接操作寄存器，而是用gpio_set_value函数来赋值。</span></p><p><span>在驱动入口函数，用of_find_node_by_path来打开gpioled节点，of_get_named_gpio来获取设备树中的gpio属性。这里的“led-gpio”是gpioled节点里的一个属性值。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307091653756.png" referrerpolicy="no-referrer" alt="image-20230709165341663"></p><p>&nbsp;</p><p><span>之后的操作没啥区别。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092137419.png" referrerpolicy="no-referrer" alt="image-20230709213745315"></p><p>&nbsp;</p><p>&nbsp;</p><h5><a name="3）应用程序" class="md-header-anchor"></a><span>3）应用程序</span></h5><p><span>不用改，用之前的LED应用程序就行。</span></p><p>&nbsp;</p><h3><a name="28-蜂鸣器实验" class="md-header-anchor"></a><span>2.8 蜂鸣器实验</span></h3><p><span>和LED驱动的原理相似，不过蜂鸣器是将GPIO设置成输出。</span></p><p>&nbsp;</p><h4><a name="281-修改设备树文件" class="md-header-anchor"></a><span>2.8.1 修改设备树文件</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092146913.png" referrerpolicy="no-referrer" alt="image-20230709214610809"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092147590.png" referrerpolicy="no-referrer" alt="image-20230709214713483"></p><p>&nbsp;</p><p>&nbsp;</p><h4><a name="282-驱动程序编写" class="md-header-anchor"></a><span>2.8.2 驱动程序编写</span></h4><p><span>驱动文件为beep.c。</span></p><p><span>我的理解：</span></p><p><span>在定义设备结构体时，定义GPIO的编号。</span></p><p><span>在写函数里，也是用gpio_set_value来设置蜂鸣器IO的值。</span></p><p><span>在驱动入口函数，用of_find_node_by_name函数来找beep节点;</span></p><p><span>用of_get_named_gpio，通过beep节点的beep-gpio属性，来获取gpio编号。</span></p><p><span>用 ret </span><strong><span>=</span></strong><span> gpio_direction_output</span><strong><span>(</span></strong><span>beep</span><strong><span>.</span></strong><span>beep_gpio</span><strong><span>,</span></strong><span> 1); 来设置默认为高电平。</span></p><p><span>设备的初始化还是用cdev_init函数来进行，设备的操作函数也是在这里被指定。</span></p><p><span>其它部分和前面的差不多。</span></p><p><span>把这些部分的驱动代码摘录如下。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092209322.png" referrerpolicy="no-referrer" alt="image-20230709220929214"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092210087.png" referrerpolicy="no-referrer" alt="image-20230709221004988"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092210502.png" referrerpolicy="no-referrer" alt="image-20230709221030362"></p><p>&nbsp;</p><h4><a name="283-应用程序编写" class="md-header-anchor"></a><span>2.8.3 应用程序编写</span></h4><p><span>应用程序为beepApp.c。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092217600.png" referrerpolicy="no-referrer" alt="image-20230709221759481"></p><p>&nbsp;</p><h4><a name="284-运行" class="md-header-anchor"></a><span>2.8.4 运行</span></h4><p><span>转到linux内核源码所在文件夹，用make clean + make dtbs编译设备树。</span></p><p><span>在本驱动文件夹下配置好Makefile，用make -j4编译生成.ko文件</span></p><p><span>arm-linux-gnueabihf-gcc beepApp.c -o beepApp，交叉编译生成应用程序beepApp</span></p><p><span>之后，像之前一样加载。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092241747.png" referrerpolicy="no-referrer" alt="image-20230709224156651"></p><p><span>可以看到，驱动被成功加载。</span></p><p><span>使用./beepApp /dev/beep 1和 ./beepApp /dev/beep 0 对蜂鸣器进行操作，成功操作蜂鸣器。</span></p><p>&nbsp;</p><h3><a name="29-linux并发与竞争" class="md-header-anchor"></a><span>2.9 Linux并发与竞争</span></h3><h4><a name="291-并发和竞争简介" class="md-header-anchor"></a><span>2.9.1 并发和竞争简介</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092318025.png" referrerpolicy="no-referrer" alt="image-20230709231823921"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092321984.png" referrerpolicy="no-referrer" alt="image-20230709232112881"></p><p>&nbsp;</p><h4><a name="292-原子操作" class="md-header-anchor"></a><span>2.9.2 原子操作</span></h4><h5><a name="1）整形操作api函数" class="md-header-anchor"></a><span>1）整形操作API函数</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092344013.png" referrerpolicy="no-referrer" alt="image-20230709234402904"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092355906.png" referrerpolicy="no-referrer" alt="image-20230709235510781"></p><p>&nbsp;</p><h5><a name="2）位操作api函数" class="md-header-anchor"></a><span>2）位操作API函数</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092356002.png" referrerpolicy="no-referrer" alt="image-20230709235604917"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307092356062.png" referrerpolicy="no-referrer" alt="image-20230709235629977"></p><p>&nbsp;</p><h4><a name="293-自旋锁" class="md-header-anchor"></a><span>2.9.3 自旋锁</span></h4><h5><a name="1）简介" class="md-header-anchor"></a><span>1）简介</span></h5><p><span>因为获取不到锁会一直自旋等待，所以适用于短时期的轻量级加锁。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307100011729.png" referrerpolicy="no-referrer" alt="image-20230710001116612"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307100011956.png" referrerpolicy="no-referrer" alt="image-20230710001150875"></p><p>&nbsp;</p><h5><a name="2）自旋锁api函数" class="md-header-anchor"></a><span>2）自旋锁API函数</span></h5><ul><li><span>最基本的API函数</span></li></ul><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221544335.png" referrerpolicy="no-referrer" alt="image-20230722154450188"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221545100.png" referrerpolicy="no-referrer" alt="image-20230722154521027"></p><p>&nbsp;</p><p><span>线程</span><strong><span>获取了自旋锁之后</span></strong><span>，当前线程不可以休眠或阻塞，也不可以被中断打断。否则，锁还被当前线程持有，但当前线程又丢失了对CPU的控制权，锁一直释放不了，就会陷入死锁。</span></p><p>&nbsp;</p><ul><li><span>先关闭本地中断再获取自旋锁相关的API函数</span></li></ul><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221603690.png" referrerpolicy="no-referrer" alt="image-20230722160332592"></p><p><span>在中断中获取/释放锁，一般不用保存中断状态，而是禁止/激活中断就可以了。在线程中获取/释放锁，一般要保存中断状态。</span></p><p>&nbsp;</p><ul><li><span>在下半部中使用自旋锁</span></li></ul><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221609203.png" referrerpolicy="no-referrer" alt="image-20230722160913141"></p><p>&nbsp;</p><h5><a name="3）其它类型的锁" class="md-header-anchor"></a><span>3）其它类型的锁</span></h5><p><span>在特定场合中使用，在Linux驱动中用的不多，在内核中用的多。</span></p><p>&nbsp;</p><ul><li><span>读写自旋锁</span></li></ul><p><span>可以并发读，读和写不可以同时进行。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221613583.png" referrerpolicy="no-referrer" alt="image-20230722161325480"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221613544.png" referrerpolicy="no-referrer" alt="image-20230722161340477"></p><p>&nbsp;</p><ul><li><span>顺序锁</span></li></ul><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221615177.png" referrerpolicy="no-referrer" alt="image-20230722161541089"></p><p>&nbsp;</p><h5><a name="4）使用注意事项" class="md-header-anchor"></a><span>4）使用注意事项</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221617242.png" referrerpolicy="no-referrer" alt="image-20230722161700170"></p><p>&nbsp;</p><p>&nbsp;</p><h4><a name="294-信号量" class="md-header-anchor"></a><span>2.9.4 信号量</span></h4><h5><a name="1）简介-n2594" class="md-header-anchor"></a><span>1）简介</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221624136.png" referrerpolicy="no-referrer" alt="image-20230722162416044"></p><p>&nbsp;</p><h5><a name="2）信号量api函数" class="md-header-anchor"></a><span>2）信号量API函数</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221625918.png" referrerpolicy="no-referrer" alt="image-20230722162512836"></p><p><strong><span>我的理解：</span></strong></p><p><span>如果申请不到信号量，就会休眠当前线程，切换到别的线程去。</span></p><p>&nbsp;</p><h4><a name="295-互斥体" class="md-header-anchor"></a><span>2.9.5 互斥体</span></h4><h5><a name="1）简介-n2603" class="md-header-anchor"></a><span>1）简介</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221631624.png" referrerpolicy="no-referrer" alt="image-20230722163125559"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221631892.png" referrerpolicy="no-referrer" alt="image-20230722163149821"></p><p>&nbsp;</p><h5><a name="2）互斥体api函数" class="md-header-anchor"></a><span>2）互斥体API函数</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221632804.png" referrerpolicy="no-referrer" alt="image-20230722163239723"></p><p>&nbsp;</p><p>&nbsp;</p><h3><a name="210-linux并发与竞争实验" class="md-header-anchor"></a><span>2.10 Linux并发与竞争实验</span></h3><p><span>学习如何在驱动中使用原子操作、自旋锁、信号量和互斥体。</span></p><h4><a name="2101-原子操作实验" class="md-header-anchor"></a><span>2.10.1 原子操作实验</span></h4><h5><a name="1）设备树文件" class="md-header-anchor"></a><span>1）设备树文件</span></h5><p><span>用的是之前LED驱动的设备树，不用再改</span></p><h5><a name="2）驱动程序-n2616" class="md-header-anchor"></a><span>2）驱动程序</span></h5><p><span>新建一个文件夹，atomic.c，里面是修改过后的驱动程序。</span></p><p><span>在之前设备树led驱动程序上修改而来，这里只贴出不一样的部分。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221648536.png" referrerpolicy="no-referrer" alt="image-20230722164831439"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221649117.png" referrerpolicy="no-referrer" alt="image-20230722164905047"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221650973.png" referrerpolicy="no-referrer" alt="image-20230722165007903"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221651650.png" referrerpolicy="no-referrer" alt="image-20230722165150571"></p><p><span>这里 int atomic_dec_and_test(atomic_t *v)  的作用是：给v减1，如果结果是0返回真，否则返回假。</span></p><p>&nbsp;</p><h5><a name="3）应用程序-n2625" class="md-header-anchor"></a><span>3）应用程序</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221659422.png" referrerpolicy="no-referrer" alt="image-20230722165903342"></p><p>&nbsp;</p><h5><a name="4）运行" class="md-header-anchor"></a><span>4）运行</span></h5><p><span>首先，参考其它驱动程序，把Makefile里的obj-m改成atomic.o，使用make -j4编译。编译成功以后就会生成一个名为“atomic.ko”的驱动模块文件。</span></p><p><span>其次，交叉编译 atomicApp.c 这个测试程序，生成可执行文件。</span></p><p><span>arm-linux-gnueabihf-gcc atomicApp.c -o atomicApp</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221717979.png" referrerpolicy="no-referrer" alt="image-20230722171739882"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221718122.png" referrerpolicy="no-referrer" alt="image-20230722171808030"></p><p><span>在打开后尝试关闭，会报错：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307221746296.png" referrerpolicy="no-referrer" alt="image-20230722174640224"></p><p>&nbsp;</p><h4><a name="2102-自旋锁实验" class="md-header-anchor"></a><span>2.10.2 自旋锁实验</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307230134092.png" referrerpolicy="no-referrer" alt="image-20230723013420971"></p><p>&nbsp;</p><h5><a name="1）设备树文件-n2640" class="md-header-anchor"></a><span>1）设备树文件</span></h5><p><span>不用修改</span></p><p>&nbsp;</p><h5><a name="2）驱动程序-n2643" class="md-header-anchor"></a><span>2）驱动程序</span></h5><p><span>新建一个文件夹，spinlock.c，里面是修改过后的驱动程序。</span></p><p><span>在之前设备树led驱动程序上修改而来，这里只贴出不一样的部分。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307230138238.png" referrerpolicy="no-referrer" alt="image-20230723013855095"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307230139358.png" referrerpolicy="no-referrer" alt="image-20230723013941223"></p><p><span>自旋锁的临界区比较短，所以临界区不能太长，在open和release里分别设置一个临界区，来修改这个变量就好了。</span></p><p><span>在open函数，上锁后，判断设备是否被使用了。如果没被使用，就把status++，说明已经被使用了，再解锁。</span></p><p><span>在release函数，上锁后，把status--，说明设备没有被使用，再解锁。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307231056966.png" referrerpolicy="no-referrer" alt="image-20230723105644838"></p><p>&nbsp;</p><h5><a name="3）应用程序-n2653" class="md-header-anchor"></a><span>3）应用程序</span></h5><p><span>测试 APP 使用 atomicApp.c 即可，将 7_atomic 中的 atomicApp.c 文件到本例程中，并将 atomicApp.c 重命名为 spinlockApp.c 即可。</span></p><p>&nbsp;</p><h5><a name="4）运行-n2656" class="md-header-anchor"></a><span>4）运行</span></h5><p><span>新建工程 - 改C++ Json - 改Makefile - 编译驱动程序 - 交叉编译应用程序 - 传到虚拟机里的rootfs下 - 启动进行挂载 - 运行。</span></p><p><span>步骤和前面一样</span></p><p>&nbsp;</p><p>&nbsp;</p><h4><a name="2103-信号量实验" class="md-header-anchor"></a><span>2.10.3 信号量实验</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307231221811.png" referrerpolicy="no-referrer" alt="image-20230723122135663"></p><h5><a name="1）设备树" class="md-header-anchor"></a><span>1）设备树</span></h5><p><span>不用改</span></p><p>&nbsp;</p><h5><a name="2）驱动程序-n2666" class="md-header-anchor"></a><span>2）驱动程序</span></h5><p><span>把有差异的部分摘录出来</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307231222883.png" referrerpolicy="no-referrer" alt="image-20230723122213775"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307231224223.png" referrerpolicy="no-referrer" alt="image-20230723122424071"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307231224508.png" referrerpolicy="no-referrer" alt="image-20230723122445395"></p><p><span>正点原子文档的解析：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307231234018.png" referrerpolicy="no-referrer" alt="image-20230723123439884"></p><p><strong><span>我的理解：</span></strong></p><p><span>如果在open函数中获取到信号量，就继续；否则，获取不到，就会一直等待，直到成功获取到才会返回0。</span></p><p>&nbsp;</p><p><strong><span>GPT对于获取信号量的解释：</span></strong></p><p><span>当 </span><code>down_interruptible()</code><span> 函数等待成功获取信号量时，它的</span><strong><span>返回值将是0</span></strong><span>，表示操作成功。也就是说，只有在成功获取到信号量后才会返回0。</span></p><p><span>但是需要注意的是，如果在等待获取信号量的过程中，调用 </span><code>down_interruptible()</code><span> 函数被中断（例如接收到了中断信号），那么返回值将是一个负值，通常是 -EINTR，表示获取信号量的操作被中断。</span></p><p><span>综上所述：</span></p><ul><li><span>如果信号量的值为1（或者更大的正数），则 </span><code>down_interruptible()</code><span> 函数的返回值为0，表示成功获取到信号量。</span></li><li><span>如果信号量的值为0，并且在等待期间没有被中断，则 </span><code>down_interruptible()</code><span> 函数将一直处于等待状态，不会返回。</span></li><li><span>如果信号量的值为0，并且在等待期间被中断，则 </span><code>down_interruptible()</code><span> 函数的返回值将是一个负值，通常是 -EINTR，表示获取信号量的操作被中断。</span></li></ul><p>&nbsp;</p><h5><a name="3）应用程序-n2688" class="md-header-anchor"></a><span>3）应用程序</span></h5><p><span>和前面一样就可以了</span></p><p>&nbsp;</p><h5><a name="4）运行-n2691" class="md-header-anchor"></a><span>4）运行</span></h5><p><span>和前面一样的步骤</span></p><p>&nbsp;</p><h4><a name="2104-互斥量实验" class="md-header-anchor"></a><span>2.10.4 互斥量实验</span></h4><h5><a name="1）设备树-n2695" class="md-header-anchor"></a><span>1）设备树</span></h5><p><span>不用改</span></p><p>&nbsp;</p><h5><a name="2）驱动程序-n2698" class="md-header-anchor"></a><span>2）驱动程序</span></h5><p><span>把有差异的部分摘录如下</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307231256458.png" referrerpolicy="no-referrer" alt="image-20230723125650374"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307231257685.png" referrerpolicy="no-referrer" alt="image-20230723125743593"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307231258118.png" referrerpolicy="no-referrer" alt="image-20230723125810041"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307231307096.png" referrerpolicy="no-referrer" alt="image-20230723130755005"></p><p>&nbsp;</p><p><strong><span>我的理解：</span></strong></p><p><span>互斥体相当于二值信号量，只不过它是专门用于互斥访问。</span></p><p>&nbsp;</p><h5><a name="3）应用程序-n2708" class="md-header-anchor"></a><span>3）应用程序</span></h5><p><span>不用改</span></p><p>&nbsp;</p><h5><a name="4）运行-n2711" class="md-header-anchor"></a><span>4）运行</span></h5><p><span>不用改</span></p><p>&nbsp;</p><h4><a name="2105-总结" class="md-header-anchor"></a><span>2.10.5 总结</span></h4><p><span>信号量和互斥体会导致休眠。如果获取不到信号量/互斥体，会休眠等待，不会直接往下运行，直到信号量/互斥体被释放。</span></p><p><span>例如，控制LED关闭，会在LED打开25s结束释放信号量/互斥体之后，关闭LED灯。</span></p><p>&nbsp;</p><p>&nbsp;</p><h3><a name="211-linux按键输入实验" class="md-header-anchor"></a><span>2.11 Linux按键输入实验</span></h3><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301149453.png" referrerpolicy="no-referrer" alt="image-20230730114945353"></p><p>&nbsp;</p><h4><a name="2111-修改设备树" class="md-header-anchor"></a><span>2.11.1 修改设备树</span></h4><h5><a name="1）添加pinctrl节点" class="md-header-anchor"></a><span>1）添加pinctrl节点</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301156320.png" referrerpolicy="no-referrer" alt="image-20230730115625242"></p><p>&nbsp;</p><h5><a name="2）添加设备key的节点" class="md-header-anchor"></a><span>2）添加设备key的节点</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301158463.png" referrerpolicy="no-referrer" alt="image-20230730115839382"></p><p>&nbsp;</p><h5><a name="3）检查端口是否被其它外设使用" class="md-header-anchor"></a><span>3）检查端口是否被其它外设使用</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301203747.png" referrerpolicy="no-referrer" alt="image-20230730120317660"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301327310.png" referrerpolicy="no-referrer" alt="image-20230730132721208"></p><p>&nbsp;</p><h4><a name="2112-编写程序" class="md-header-anchor"></a><span>2.11.2 编写程序</span></h4><h5><a name="1）驱动程序-n2734" class="md-header-anchor"></a><span>1）驱动程序</span></h5><p><span>把不一样的部分和重要的部分摘录如下。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301338157.png" referrerpolicy="no-referrer" alt="image-20230730133815062"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301339539.png" referrerpolicy="no-referrer" alt="image-20230730133914444"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301342533.png" referrerpolicy="no-referrer" alt="image-20230730134245425"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301345767.png" referrerpolicy="no-referrer" alt="image-20230730134537650"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301346410.png" referrerpolicy="no-referrer" alt="image-20230730134638324"></p><p><span>关键在于读取按键值。</span></p><p><span>按下设置为0xF0，没按下设置为0x00。</span></p><p>&nbsp;</p><h5><a name="2）应用程序-n2744" class="md-header-anchor"></a><span>2）应用程序</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301401070.png" referrerpolicy="no-referrer" alt="image-20230730140151967"></p><p><span>第 51~56 行，循环读取/dev/key 文件，也就是循环读取按键值，并且将按键值打印出来。</span></p><p>&nbsp;</p><h3><a name="212-linux内核定时器实验" class="md-header-anchor"></a><span>2.12 Linux内核定时器实验</span></h3><h4><a name="2121-内核时间管理简介" class="md-header-anchor"></a><span>2.12.1 内核时间管理简介</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301658485.png" referrerpolicy="no-referrer" alt="image-20230730165822378"></p><p><span>Linux内核源码路径下的.config文件：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301701399.png" referrerpolicy="no-referrer" alt="image-20230730170149325"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301703565.png" referrerpolicy="no-referrer" alt="image-20230730170301474"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301703459.png" referrerpolicy="no-referrer" alt="image-20230730170342381"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301712937.png" referrerpolicy="no-referrer" alt="image-20230730171208832"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301713237.png" referrerpolicy="no-referrer" alt="image-20230730171356157"></p><p><strong><span>我的理解：</span></strong></p><p><span>用了这几个比较函数，相当于不用对具体的jiffies数值进行判断，而是能够直接知道两个时间戳的先后顺序。</span></p><p>&nbsp;</p><h4><a name="2122-内核定时器简介" class="md-header-anchor"></a><span>2.12.2 内核定时器简介</span></h4><p><span>超时时间到了就会关闭，所以如果需要周期性进行，需要在处理函数里重新开启定时器。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301723374.png" referrerpolicy="no-referrer" alt="image-20230730172343274"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301732353.png" referrerpolicy="no-referrer" alt="image-20230730173206251"></p><p><span>接下来是实际的代码实现</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301732569.png" referrerpolicy="no-referrer" alt="image-20230730173244496"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301733933.png" referrerpolicy="no-referrer" alt="image-20230730173343842"></p><p>&nbsp;</p><h5><a name="几个短延时函数" class="md-header-anchor"></a><span>几个短延时函数</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301734353.png" referrerpolicy="no-referrer" alt="image-20230730173436277"></p><p>&nbsp;</p><h4><a name="2123-程序编写" class="md-header-anchor"></a><span>2.12.3 程序编写</span></h4><p><span>本实验就是控制LED灯的定时亮灭。设备树就是按照之前LED那样子配置就可以了。</span></p><h5><a name="补充ioctl命令" class="md-header-anchor"></a><span>补充：ioctl命令</span></h5><p><span>在 Linux 内核编程中，</span><code>ioctl</code><span> 是用于设备控制的系统调用。它可以用来与设备进行交互，并执行特定的操作。</span><code>ioctl</code><span> 函数接受三个参数：文件描述符、请求号和一个可选的参数。请求号通常由命令码和命令类型组成。</span></p><p><span>而 </span><code>_IO</code><span> 宏是一个用于生成 ioctl 命令的辅助宏。它接受两个参数：命令类型和命令序号。其中，命令类型通常是一个唯一的字符，而命令序号则是命令的标识符。</span></p><p><span>在这个宏定义中，</span><code>CLOSE_CMD</code><span> 被定义为一个 </span><code>_IO</code><span> 命令，命令类型为 </span><code>0xEF</code><span>，命令序号为 </span><code>0x1</code><span>。这意味着 </span><code>CLOSE_CMD</code><span> 是一个用于关闭设备的 ioctl 命令。</span></p><p><span>在使用这个宏定义时，可以通过调用 </span><code>ioctl</code><span> 函数并将相应的文件描述符和 </span><code>CLOSE_CMD</code><span> 作为参数传递来触发关闭设备的操作。</span></p><p>&nbsp;</p><h5><a name="1）驱动程序编写" class="md-header-anchor"></a><span>1）驱动程序编写</span></h5><p><span>只摘录重要的和不一样的部分。（设备还是gpioled这个设备）</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301812847.png" referrerpolicy="no-referrer" alt="image-20230730181236747"></p><p><span>在open函数中设置定时器周期（默认周期设置为1s）</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301813362.png" referrerpolicy="no-referrer" alt="image-20230730181357281"></p><p><span>设置ioctl函数。主要是用于输入不同的命令cmd，根据不同的cmd来进行不同的操作。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301816604.png" referrerpolicy="no-referrer" alt="image-20230730181624526"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301818648.png" referrerpolicy="no-referrer" alt="image-20230730181804558"></p><p><span>在设备操作函数中，设置.unlocker_ioctl为自定义的timer_unlocked_ioctl函数。</span></p><p><strong><span>补充：</span></strong></p><p><span>在 Linux 内核的文件操作结构 </span><code>file_operations</code><span> 中，</span><code>.ioctl</code><span> 和 </span><code>.unlocked_ioctl</code><span> 是两个不同的成员。</span></p><ol start='' ><li><code>.ioctl</code><span>：这是用于处理 </span><code>ioctl</code><span> 系统调用的函数指针。</span><code>ioctl</code><span> 是一个通用的系统调用，用于控制设备和执行特定操作。当用户空间调用 </span><code>ioctl</code><span> 系统调用时，内核会调用相应设备的 </span><code>.ioctl</code><span> 函数来处理这个请求。</span></li><li><code>.unlocked_ioctl</code><span>：这也是处理 </span><code>ioctl</code><span> 系统调用的函数指针，但与 </span><code>.ioctl</code><span> 不同的是，</span><code>.unlocked_ioctl</code><span> 是在内部代码中使用的未加锁版本。这个函数指针</span><strong><span>允许驱动程序在无需持有设备锁的情况下处理</span></strong><span> </span><code>ioctl</code><span> 请求。这对于某些特定情况下的并发访问可能是必要的，以避免资源竞争和死锁问题。</span>
<span>（对于本驱动来说，是在switch case当中实际处理时，才进行上锁和解锁）</span></li></ol><p><span>因此，</span><code>.ioctl</code><span> 和 </span><code>.unlocked_ioctl</code><span> 的不同之处在于它们处理 </span><code>ioctl</code><span> 请求时的锁机制。通常情况下，开发者会根据具体需求选择合适的函数来处理 </span><code>ioctl</code><span> 请求，以确保正确地进行设备控制并避免竞争条件。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301829628.png" referrerpolicy="no-referrer" alt="image-20230730182939545"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301829499.png" referrerpolicy="no-referrer" alt="image-20230730182952403"></p><p>&nbsp;</p><p><span>在设备初始化的init函数中，初始化定时器以及对应的回调函数。因为没设置周期，所以还不会运行。在出口处也要删除定时器。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301840900.png" referrerpolicy="no-referrer" alt="image-20230730184014799"></p><p><span>总结：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301848460.png" referrerpolicy="no-referrer" alt="image-20230730184837351"></p><p>&nbsp;</p><h5><a name="2）应用程序编写" class="md-header-anchor"></a><span>2）应用程序编写</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301851689.png" referrerpolicy="no-referrer" alt="image-20230730185116610"></p><p><span>只摘录重要的和不一样的内容。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301851654.png" referrerpolicy="no-referrer" alt="image-20230730185148574"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307301852994.png" referrerpolicy="no-referrer" alt="image-20230730185220904"></p><p><span>最后是通过ioctl函数，调用驱动中的ioctl函数。</span></p><p>&nbsp;</p><h5><a name="3）运行测试" class="md-header-anchor"></a><span>3）运行测试</span></h5><p><span>没啥好说的，和前面一样，详见正点原子文档。</span></p><p>&nbsp;</p><p>&nbsp;</p><h3><a name="213-linux中断实验" class="md-header-anchor"></a><span>2.13 Linux中断实验</span></h3><h4><a name="2131-linux中断api函数" class="md-header-anchor"></a><span>2.13.1 Linux中断API函数</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302038135.png" referrerpolicy="no-referrer" alt="image-20230730203836027"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302043569.png" referrerpolicy="no-referrer" alt="image-20230730204307478"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302049552.png" referrerpolicy="no-referrer" alt="image-20230730204952453"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302051598.png" referrerpolicy="no-referrer" alt="image-20230730205116507"></p><p>&nbsp;</p><h4><a name="2132-上半部与下半部" class="md-header-anchor"></a><span>2.13.2 上半部与下半部</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302055637.png" referrerpolicy="no-referrer" alt="image-20230730205552547"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302056820.png" referrerpolicy="no-referrer" alt="image-20230730205620735"></p><h5><a name="linux内核提供的下半部机制" class="md-header-anchor"></a><span>Linux内核提供的下半部机制：</span></h5><h5><a name="1）软中断" class="md-header-anchor"></a><span>1）软中断</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302103776.png" referrerpolicy="no-referrer" alt="image-20230730210319670"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302105174.png" referrerpolicy="no-referrer" alt="image-20230730210550080"></p><p><span>软中断有一个softirq_action结构体，结构体里是一个函数指针。通过大小为10的softirq_action类型的数组，定义了10个软中断。</span></p><p><span>软中断需要在编译的时候静态注册。用softirq_init函数初始化软中断。</span></p><p><span>要使用软中断，要先用open_softirq函数注册对应的软中断处理函数。</span></p><p><span>注册好软中断后，</span><strong><span>需要通过raise_softirq函数触发</span></strong><span>。按我的理解，raise_softirq函数就类似于tasklet_schedule函数，进入中断下半部。</span></p><p>&nbsp;</p><p>&nbsp;</p><h5><a name="2）tasklet" class="md-header-anchor"></a><span>2）tasklet</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302124032.png" referrerpolicy="no-referrer" alt="image-20230730212410941"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302129230.png" referrerpolicy="no-referrer" alt="image-20230730212916127"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302136279.png" referrerpolicy="no-referrer" alt="image-20230730213654194"></p><p><strong><span>补充：</span></strong></p><p><code>raise_softirq</code><span> 函数其实是用于触发软中断，将软中断放入软中断队列中，最终由软中断处理器调度执行。而 </span><code>tasklet_schedule</code><span> 函数是用于触发 Tasklet，将 Tasklet 放入底半部队列中，等待中断结束后执行。</span></p><p><span>在内核的设计中，软中断和 Tasklet 都可以用来处理延迟执行的工作。它们的主要区别在于底层实现和调度机制。软中断是通过软中断处理器进行调度和处理的，而 Tasklet 是使用底半部的概念来实现的。在触发方面，</span><code>raise_softirq</code><span> 将软中断放入队列，由软中断处理器处理，而 </span><code>tasklet_schedule</code><span> 将 Tasklet 放入底半部队列，在中断上下文结束后执行。</span></p><p><span>需要注意的是，Tasklet 在调度时有一些优化机制，例如</span><strong><span>同一 Tasklet 在同一个处理器上不会被重复调度</span></strong><span>，这样可以提高执行效率。而软中断则没有这种优化机制，可以在同一个软中断处理程序执行期间被重入。</span></p><p><span>总结来说，</span><code>raise_softirq</code><span> 函数触发软中断，</span><code>tasklet_schedule</code><span> 函数触发 Tasklet，并将它们放入相应的队列中，等待处理。而具体的底层实现和调度机制使得软中断和 Tasklet 在使用上略有区别。</span></p><p>&nbsp;</p><h5><a name="3）工作队列" class="md-header-anchor"></a><span>3）工作队列</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302145990.png" referrerpolicy="no-referrer" alt="image-20230730214536886"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302152588.png" referrerpolicy="no-referrer" alt="image-20230730215233484"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302153102.png" referrerpolicy="no-referrer" alt="image-20230730215326013"></p><p>&nbsp;</p><h5><a name="总结" class="md-header-anchor"></a><span>总结</span></h5><p><span>一般都是在驱动入口函数外定义软中断/tasklet/工作。</span></p><p><span>在驱动入口函数处进行初始化，并注册中断处理函数。</span></p><p><span>在中断处理函数中，进行软中断/task/工作队列的调度，在相应的处理函数中进行中断下半部的处理。</span></p><p>&nbsp;</p><h4><a name="2133-设备树中断信息节点" class="md-header-anchor"></a><span>2.13.3 设备树中断信息节点</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307302216736.png" referrerpolicy="no-referrer" alt="image-20230730221608629"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310016263.png" referrerpolicy="no-referrer" alt="image-20230731001630157"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310017241.png" referrerpolicy="no-referrer" alt="image-20230731001733152"></p><p>&nbsp;</p><h4><a name="2134-获取中断号" class="md-header-anchor"></a><span>2.13.4 获取中断号</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310020731.png" referrerpolicy="no-referrer" alt="image-20230731002036645"></p><p><strong><span>irq_of_parse_and_map</span></strong><span>可以</span><strong><span>从interupts属性中</span></strong><span>提取对应的中断号。</span></p><p><span>如果用到gpio，可以用</span><strong><span>gpio_to_irq</span></strong><span>来获取gpio对应的中断号。</span></p><p>&nbsp;</p><h4><a name="2135-在设备树中添加中断相关属性" class="md-header-anchor"></a><span>2.13.5 在设备树中添加中断相关属性</span></h4><p><span>本章实验使用到了按键 KEY0，按键 KEY0 使用中断模式，因此需要在“key”节点下添加中断相关属性，添加完成以后的“key”节点内容如下所示：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310032144.png" referrerpolicy="no-referrer" alt="image-20230731003259042"></p><p>&nbsp;</p><h4><a name="2136-按键中断驱动程序编写" class="md-header-anchor"></a><span>2.13.6 按键中断驱动程序编写</span></h4><p><span>只摘录变化的和重要的部分。</span></p><p><span>太多了，分几段来分析。</span></p><h5><a name="1）中断结构体定义设备结构体定义中断服务函数定时器服务函数" class="md-header-anchor"></a><span>（1）中断结构体定义，设备结构体定义，中断服务函数，定时器服务函数</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310035929.png" referrerpolicy="no-referrer" alt="image-20230731003502822"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310040341.png" referrerpolicy="no-referrer" alt="image-20230731004045236"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310042160.png" referrerpolicy="no-referrer" alt="image-20230731004206076"></p><p><span>正点原子文档的解释：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310047745.png" referrerpolicy="no-referrer" alt="image-20230731004738657"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310047055.png" referrerpolicy="no-referrer" alt="image-20230731004756968"></p><p><strong><span>我的理解：</span></strong></p><p><span>定义了一个中断描述结构体，一个设备结构体。在设备结构体中，定义了中断描述结构体数组，数组个数为按键个数。</span></p><p><span>在按键的中断处理函数中，传入的参数为中断号和设备结构体。打开定时器，设置延时时间为10ms。10ms到后，实际是在定时器服务函数中，进行按键的读取。</span></p><p><span>在定时器服务函数中，传入的参数也是设备结构体。首先设置num，也就是按键的编号，并且通过 </span><strong><span>keydesc = &amp;dev-&gt;irqkeydesc[num]</span></strong><span> 来指定这个按键对应的中断描述结构体（当然在开发板上只有一个按键，实际会有多个）。</span></p><p><span>然后读取按键值，如果是0说明按键被按下，设置设备结构体中的按键值。是1说明按键松开，也可以记录，同时通过修改release_key为1，来标记按键被松开。</span></p><p>&nbsp;</p><h5><a name="2）按键io初始化" class="md-header-anchor"></a><span>（2）按键io初始化</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310103065.png" referrerpolicy="no-referrer" alt="image-20230731010319937"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310111801.png" referrerpolicy="no-referrer" alt="image-20230731011135699"></p><p>&nbsp;</p><p><span>正点原子文档的解释：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310113907.png" referrerpolicy="no-referrer" alt="image-20230731011353802"></p><p>&nbsp;</p><p><strong><span>我的理解：</span></strong></p><p><span>io的申请和前面区别不大，主要是多了设置中断、获取中断号等。</span></p><p><strong><span>imx6uirq.irqkeydesc[0].handler = key0_handler</span></strong><span>  这里是指定imx6uirq.irqkeydesc[0]的中断处理函数为</span><strong><span>key0_handler</span></strong></p><p><span>并且初始化了它的按键值。</span></p><p><span>然后用 </span><strong><span>request_irq</span></strong><span> 函数来申请中断，几个参数分别是：imx6uirq.irqkeydesc[i].irqnum， imx6uirq.irqkeydesc[i].handler， </span>
<span>IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING， imx6uirq.irqkeydesc[i].name， &amp;imx6uirq</span></p><p><span>分别对应要申请中断的中断号（这里是直接从设备树中获取），中断处理函数，中断标志（这里是下降沿和上升沿都触发），中断名字，设备结构体。</span></p><p><span>中断名字在前面通过这两句来定义：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">memset</span>(<span class="cm-variable">imx6uirq</span>.<span class="cm-variable">irqkeydesc</span>[<span class="cm-variable">i</span>].<span class="cm-variable">name</span>, <span class="cm-number">0</span>, <span class="cm-keyword">sizeof</span>(<span class="cm-variable">imx6uirq</span>.<span class="cm-variable">irqkeydesc</span>[<span class="cm-variable">i</span>].<span class="cm-variable">name</span>));<span class="cm-tab" role="presentation" cm-text="	">    </span><span class="cm-comment">/* 缓冲区清零 */</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-variable">sprintf</span>(<span class="cm-variable">imx6uirq</span>.<span class="cm-variable">irqkeydesc</span>[<span class="cm-variable">i</span>].<span class="cm-variable">name</span>, <span class="cm-string">"KEY%d"</span>, <span class="cm-variable">i</span>);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/*</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">第一句代码 memset(imx6uirq.irqkeydesc[i].name, 0, sizeof(imx6uirq.irqkeydesc[i].name)) 的作用是</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">将 imx6uirq.irqkeydesc[i].name 数组中的内容全部设置为0。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">这样做可以确保在后续使用该数组之前，它是一个全零的缓冲区。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">第二句代码 sprintf(imx6uirq.irqkeydesc[i].name, "KEY%d", i) 的作用是使用格式化字符串</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">将 imx6uirq.irqkeydesc[i].name 数组赋值为 "KEY" 后跟一个整数。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">其中的 %d 表示将 i 的值以十进制形式转换为字符串，并将结果拼接到 "KEY" 后面。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">这样就实现了给 imx6uirq.irqkeydesc[i].name 数组赋予了以 "KEY" 开头、后面跟随一个整数的字符串。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">综合起来，这两句代码的目的是先将 imx6uirq.irqkeydesc[i].name 数组清零，然后通过 sprintf 函数将一个以 "KEY" 开头、后面跟随一个整数的字符串赋值给该数组。</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">*/</span></span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 368px;"></div><div class="CodeMirror-gutters" style="display: none; height: 368px;"></div></div></div></pre><p><span>最后是创建定时器，并且指定定时器的服务函数为</span><strong><span>timer_function</span></strong></p><p>&nbsp;</p><h5><a name="3）openread操作结构体" class="md-header-anchor"></a><span>（3）open，read，操作结构体</span></h5><p><span>open没什么特别的，在里面设置私有数据： filp</span><strong><span>-&gt;</span></strong><span>private_data = &amp;imx6uirq  即可</span></p><p><span>read函数和操作结构体如下。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310134321.png" referrerpolicy="no-referrer" alt="image-20230731013423214"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310134855.png" referrerpolicy="no-referrer" alt="image-20230731013442754"></p><p>&nbsp;</p><p><span>正点原子代码的解释：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310135468.png" referrerpolicy="no-referrer" alt="image-20230731013537379"></p><p><strong><span>我的理解：</span></strong></p><p><span>在定时器服务函数中，按键松开才会把release置1，这样才算一次有效按键。在读取并向用户空间发送之后，又把release置0。这样，直到下次按键松开，才是依次有效的按键。</span></p><p>&nbsp;</p><h5><a name="4）驱动入口出口函数" class="md-header-anchor"></a><span>（4）驱动入口/出口函数</span></h5><p><span>入口函数没什么不一样，要把两个原子变量 imx6uirq</span><strong><span>.</span></strong><span>keyvalue 和 imx6uirq</span><strong><span>.</span></strong><span>releasekey 给初始化，并且调用keyio_init() 来对按键的io进行初始化。</span></p><p><span>出口函数调用 del_timer_sync 函数删除定时器，并且轮流释放申请的所有按键中断。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310142955.png" referrerpolicy="no-referrer" alt="image-20230731014201856"></p><p>&nbsp;</p><p><span>至此，驱动程序已经分析完毕。</span></p><p>&nbsp;</p><h4><a name="2137-应用程序编写" class="md-header-anchor"></a><span>2.13.7 应用程序编写</span></h4><p><span>测试 APP 要实现的内容很简单，通过不断的读取/dev/imx6uirq 文件来获取按键值，当按键按下以后就会将获取到的按键值输出在终端上。</span></p><p><span>只摘录不一样的和重要的部分。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310200399.png" referrerpolicy="no-referrer" alt="image-20230731020031307"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310200883.png" referrerpolicy="no-referrer" alt="image-20230731020044792"></p><p>&nbsp;</p><h4><a name="2138-运行测试" class="md-header-anchor"></a><span>2.13.8 运行测试</span></h4><p><span>可以看到，按下一次按键才更新一次，不会出现抖动。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307310109655.png" referrerpolicy="no-referrer" alt="image-20230731010921571"></p><p>&nbsp;</p><p>&nbsp;</p><h3><a name="214-linux阻塞和非阻塞io实验" class="md-header-anchor"></a><span>2.14 Linux阻塞和非阻塞IO实验</span></h3><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307312329724.png" referrerpolicy="no-referrer" alt="image-20230731232945534"></p><p><span> </span></p><h4><a name="2141-等待队列" class="md-header-anchor"></a><span>2.14.1 等待队列</span></h4><p><span>一般来说，如果使用阻塞io，就需要用到这个机制。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307312336646.png" referrerpolicy="no-referrer" alt="image-20230731233619497"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307312346810.png" referrerpolicy="no-referrer" alt="image-20230731234625610"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307312349807.png" referrerpolicy="no-referrer" alt="image-20230731234948678"></p><p>&nbsp;</p><p><strong><span>我的理解</span></strong><span>：</span></p><ol start='' ><li><p><span>等待队列头（wait queue head）：</span></p><ul><li><span>等待队列头是一个数据结构，用于管理一个等待队列中的等待者（进程或线程）。每个等待队列头对应一个特定的条件。</span></li><li><span>等待队列头由</span><code>wait_queue_head_t</code><span>类型表示，定义在 </span><code>&lt;linux/wait.h&gt;</code><span> 头文件中，并且是一个双向链表。</span></li><li><span>等待队列头具有</span><strong><span>两个主要操作</span></strong><span>：</span><strong><span>添加等待项</span></strong><span>和</span><strong><span>唤醒等待者</span></strong><span>。</span><strong><span>在等待队列头上等待的进程或线程会被阻塞，直到被唤醒</span></strong><span>。</span></li></ul></li><li><p><span>等待队列项（wait queue item）：</span></p><ul><li><span>等待队列项是</span><strong><span>等待队列中的一个元素</span></strong><span>，表示一个特定的等待者（进程或线程）。每个等待队列项对应一个等待者。</span></li><li><span>等待队列项由</span><code>wait_queue_t</code><span>类型表示，定义在 </span><code>&lt;linux/wait.h&gt;</code><span> 头文件中。</span></li><li><span>等待队列项包含了等待者的固有属性和状态信息，如进程号、等待状态、私有数据等。</span></li></ul></li></ol><p><span>在使用等待队列头和等待队列项时，通常的流程是：</span></p><ol start='' ><li><span>创建一个等待队列头（</span><code>wait_queue_head_t</code><span>对象）。</span></li><li><span>创建一个等待队列项（</span><code>wait_queue_t</code><span>对象），并设置相应的属性。</span></li><li><span>将等待队列项添加到等待队列头（使用 </span><code>add_wait_queue()</code><span> 或类似函数）。</span></li><li><span>进程或线程在等待队列头上等待（如调用 </span><code>wait_event()</code><span> 或类似函数）。</span></li><li><span>当条件满足时，唤醒等待队列头上的等待者（使用 </span><code>wake_up()</code><span> 或类似函数）。</span></li></ol><p>&nbsp;</p><h4><a name="2142-轮询" class="md-header-anchor"></a><span>2.14.2 轮询</span></h4><p><span>如果使用非阻塞io，就要使用轮询机制。一般是select、poll 和 epoll 这三个函数。</span></p><h5><a name="1）select函数" class="md-header-anchor"></a><span>1）select函数</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010001255.png" referrerpolicy="no-referrer" alt="image-20230801000158108"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010010175.png" referrerpolicy="no-referrer" alt="image-20230801001025975"></p><p>&nbsp;</p><h5><a name="2）poll函数" class="md-header-anchor"></a><span>2）poll函数</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010015521.png" referrerpolicy="no-referrer" alt="image-20230801001506325"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010015442.png" referrerpolicy="no-referrer" alt="image-20230801001537258"></p><p>&nbsp;</p><h5><a name="3）epoll函数" class="md-header-anchor"></a><span>3）epoll函数</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202307312357434.png" referrerpolicy="no-referrer" alt="image-20230731235702274"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010000271.png" referrerpolicy="no-referrer" alt="image-20230801000002097"></p><p>&nbsp;</p><h4><a name="2143-linux驱动下的poll函数" class="md-header-anchor"></a><span>2.14.3 Linux驱动下的poll函数</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010034162.png" referrerpolicy="no-referrer" alt="image-20230801003411006"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010034643.png" referrerpolicy="no-referrer" alt="image-20230801003429526"></p><p>&nbsp;</p><h4><a name="2144-阻塞io实验" class="md-header-anchor"></a><span>2.14.4 阻塞io实验</span></h4><h5><a name="1）驱动程序-n2992" class="md-header-anchor"></a><span>1）驱动程序</span></h5><p><span>只摘录重要的和不一样的部分。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010037040.png" referrerpolicy="no-referrer" alt="image-20230801003751921"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010039514.png" referrerpolicy="no-referrer" alt="image-20230801003915343"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010042982.png" referrerpolicy="no-referrer" alt="image-20230801004227808"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010043413.png" referrerpolicy="no-referrer" alt="image-20230801004348257"></p><p>&nbsp;</p><p><span>正点原子文档的解释：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308010051794.png" referrerpolicy="no-referrer" alt="image-20230801005139630"></p><p>&nbsp;</p><p><strong><span>chatGPT的理解：</span></strong></p><ol start='' ><li><span>定义了一个等待队列头</span><code>r_wait</code><span>，用于存储等待的进程。</span></li><li><span>当没有按键按下时，执行</span><code>add_wait_queue</code><span>函数，将进程加入到等待队列中，将等待队列添加到等待队列头，设置任务状态后，使用schedule进行依次调度，使得当前进程进入可中断睡眠状态。</span></li><li><span>如果有按键按下，会唤醒等待队列中的进程（在定时器服务函数中进行唤醒）。</span></li><li><span>当按键按下时，会调用</span><code>wake_up_interruptible</code><span>函数来唤醒等待队列中的进程。（按键按下又释放，触发中断，消抖后在定时器处理函数中调用）</span></li><li><span>在驱动的读操作函数</span><code>imx6uirq_read</code><span>中，通过判断按键是否按下来确定是否继续往下执行。</span></li></ol><p><span>需要注意的是，在代码中使用了</span><code>DECLARE_WAITQUEUE</code><span>宏来定义一个等待队列项，同时使用</span><code>add_wait_queue</code><span>和</span><code>remove_wait_queue</code><span>函数将其添加到/从等待队列中。此外，使用</span><code>__set_current_state</code><span>函数将当前进程设置为睡眠或运行态，以实现进程的睡眠和唤醒操作。</span></p><p>&nbsp;</p><p><strong><span>我的理解：</span></strong></p><p><span>没有按键按下时，将进程加入到等待队列中，并使得当前进程进入可中断睡眠状态。当按键按下时，唤醒等待队列中的进程。</span></p><p><span>等待队列头在设备结构体中定义，在按键io初始化的最后用 </span><strong><span>init_waitqueue_head(&amp;imx6uirq.r_wait)</span></strong><span> 来初始化。</span></p><p><span>在read函数中，通过 </span><strong><span>DECLARE_WAITQUEUE(wait, current)</span></strong><span> 定义一个等待队列，（这里的wait是新定义的队列项，current指向当前的进程）。</span>
<strong><span>add_wait_queue(&amp;dev-&gt;r_wait, &amp;wait)</span></strong><span> 将等待队列添加到等待队列头，</span><strong><span>__set_current_state</span></strong><span>(TASK_INTERRUPTIBLE) 设置任务状态 ，</span><strong><span>schedule()</span></strong><span> 进行一次任务切换。调用完schedule之后，任务从此处休眠。如果被唤醒，将从这个休眠点开始继续执行。</span></p><p><span>被唤醒后，判断不是被信号量唤醒，而是被中断唤醒，</span><strong><span>__set_current_state(TASK_RUNNING)</span></strong><span>， 将当前任务设置为运行状态 ，</span>
<strong><span>remove_wait_queue(&amp;dev-&gt;r_wait, &amp;wait)</span></strong><span> 将对应的队列项从等待队列头删除 。</span></p><p>&nbsp;</p><p>&nbsp;</p><h5><a name="2）应用程序-n3023" class="md-header-anchor"></a><span>2）应用程序</span></h5><p><span>将 imx6uirqApp.c 复制到本节实验文件夹下，并且重命名为 blockioApp.c，不需要修改任何内容。</span></p><p>&nbsp;</p><h5><a name="3）运行测试-n3026" class="md-header-anchor"></a><span>3）运行测试</span></h5><p><span>没啥好说的，照旧。</span></p><p>&nbsp;</p><h4><a name="2145-非阻塞io实验" class="md-header-anchor"></a><span>2.14.5 非阻塞io实验</span></h4><h5><a name="1）驱动程序-n3030" class="md-header-anchor"></a><span>1）驱动程序</span></h5><p><span>只记录重要的部分。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072258992.png" referrerpolicy="no-referrer" alt="image-20230807225758747"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072258168.png" referrerpolicy="no-referrer" alt="image-20230807225848987"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072259645.png" referrerpolicy="no-referrer" alt="image-20230807225903488"></p><p>&nbsp;</p><p><strong><span>我的理解：</span></strong></p><p><span>在read函数中，判断是否为非阻塞式读取访问，如果是的话就判断按键是否有效，也就是判断一下有没有按键按下，如果没有的话就返回-EAGAIN。</span></p><p><span>当应用程序调用 select 或者 poll 函数的时候 imx6uirq_poll 函数就会执行。第 246 行调用 poll_wait 函数</span><strong><span>将等待队列头添加到 poll_table 中</span></strong><span>，第 248~250 行判断按键是否有效，如果按键有效的话就向应用程序返回 POLLIN 这个事件，表示有数据可以读取。</span></p><p><span>在应用程序中，调用select/poll函数时，根据返回值来做处理。（一般来说，0是超时，小于0是错误，大于0才是对的）</span></p><p>&nbsp;</p><h5><a name="2）测试程序" class="md-header-anchor"></a><span>2）测试程序</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072302283.png" referrerpolicy="no-referrer" alt="image-20230807230200080"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072303837.png" referrerpolicy="no-referrer" alt="image-20230807230340611"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072303952.png" referrerpolicy="no-referrer" alt="image-20230807230355766"></p><p>&nbsp;</p><h5><a name="3）运行测试-n3046" class="md-header-anchor"></a><span>3）运行测试</span></h5><p><span>没啥好说的，照旧。</span></p><p>&nbsp;</p><h3><a name="215-异步通知实验" class="md-header-anchor"></a><span>2.15 异步通知实验</span></h3><h4><a name="2151-异步通知原理" class="md-header-anchor"></a><span>2.15.1 异步通知原理</span></h4><p><span>驱动程序能主动向应用程序发出通知，报告自己可以访问，然后应用程序在从驱动程序中读取或写入数据，类似于中断。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072321403.png" referrerpolicy="no-referrer" alt="image-20230807232139240"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072330864.png" referrerpolicy="no-referrer" alt="image-20230807233042641"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072331997.png" referrerpolicy="no-referrer" alt="image-20230807233137781"></p><p>&nbsp;</p><h4><a name="2152-驱动中的信号处理" class="md-header-anchor"></a><span>2.15.2 驱动中的信号处理</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072341591.png" referrerpolicy="no-referrer" alt="image-20230807234156480"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072342577.png" referrerpolicy="no-referrer" alt="image-20230807234212468"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072347264.png" referrerpolicy="no-referrer" alt="image-20230807234720144"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072348109.png" referrerpolicy="no-referrer" alt="image-20230807234804000"></p><p>&nbsp;</p><h4><a name="2153-应用程序对异步通知的处理" class="md-header-anchor"></a><span>2.15.3 应用程序对异步通知的处理</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308072354600.png" referrerpolicy="no-referrer" alt="image-20230807235431506"></p><p>&nbsp;</p><h4><a name="2154-驱动程序编写" class="md-header-anchor"></a><span>2.15.4 驱动程序编写</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080008051.png" referrerpolicy="no-referrer" alt="image-20230808000842952"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080009295.png" referrerpolicy="no-referrer" alt="image-20230808000919202"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080010647.png" referrerpolicy="no-referrer" alt="image-20230808001045536"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080011241.png" referrerpolicy="no-referrer" alt="image-20230808001134146"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080012021.png" referrerpolicy="no-referrer" alt="image-20230808001219909"></p><p>&nbsp;</p><h4><a name="2155-应用程序编写" class="md-header-anchor"></a><span>2.15.5 应用程序编写</span></h4><p><span>测试 APP 要实现的内容很简单，设置 SIGIO 信号的处理函数为 sigio_signal_func，当驱动程序向应用程序发送 SIGIO 信号以后， sigio_signal_func 函数就会执行。sigio_signal_func 函数内容很简单，就是通过 read 函数读取按键值。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080106355.png" referrerpolicy="no-referrer" alt="image-20230808010622108"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080106393.png" referrerpolicy="no-referrer" alt="image-20230808010639248"></p><p><span>三句代码的作用是在设备驱动程序中设置异步通知的相关参数和标志。</span></p><ol start='' ><li><code>fcntl(fd, F_SETOWN, getpid());</code><span>： 这句代码的作用是</span><strong><span>将当前进程的进程ID（PID）设置为文件描述符（fd）所引用的文件的所有者</span></strong><span>。通过调用 </span><code>getpid()</code><span> 函数获取当前进程的PID，并使用 </span><code>F_SETOWN</code><span> 标志将该PID设置为文件的所有者。这一步是为了将异步通知的信号发送给当前进程。</span></li><li><code>flags = fcntl(fd, F_GETFD);</code><span>： 这句代码的作用是获取文件描述符（fd）的标志位。通过调用 </span><code>fcntl()</code><span> 函数，使用 </span><code>F_GETFD</code><span> 标志获取文件描述符的标志位，并将其保存在变量 </span><code>flags</code><span> 中，以备后续操作使用。</span></li><li><code>fcntl(fd, F_SETFL, flags | FASYNC);</code><span>： 这句代码的作用是</span><strong><span>将异步通知的标志位（FASYNC）添加到文件描述符（fd）的标志位中</span></strong><span>。使用 </span><code>F_SETFL</code><span> 标志和位运算符 </span><code>|</code><span>，将异步通知标志位 </span><code>FASYNC</code><span> 添加到之前获取的标志位 </span><code>flags</code><span> 中，然后通过调用 </span><code>fcntl()</code><span> 函数将新的标志位设置给文件描述符。</span></li></ol><p><span>其中，</span><code>fcntl()</code><span> 是一个系统调用函数，用于对文件描述符进行各种控制操作。它可以获取或设置文件描述符的各种属性和标志位，如文件状态标志、文件访问模式、文件锁等。</span></p><p><span>在这里，第一个 </span><code>fcntl()</code><span> 调用使用 </span><code>F_SETOWN</code><span> 标志将设备文件的所有者设置为当前进程，以便进程能够接收异步通知信号。第二个 </span><code>fcntl()</code><span> 调用使用 </span><code>F_GETFD</code><span> 标志获取文件描述符的标志位。第三个 </span><code>fcntl()</code><span> 调用使用 </span><code>F_SETFL</code><span> 标志和位运算符将异步通知的标志位添加到文件描述符的标志位中，以启用异步通知功能。</span></p><p>&nbsp;</p><h4><a name="2156-测试" class="md-header-anchor"></a><span>2.15.6 测试</span></h4><p><span>和之前一样</span></p><p>&nbsp;</p><p>&nbsp;</p><h2><a name="三platform设备驱动" class="md-header-anchor"></a><span>三、platform设备驱动</span></h2><p><span>在Linux设备树文件的一个节点设置了compatible属性，这是怎么找到代码中对应的compatible属性并且匹配的呢？</span></p><p><span>例如：</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" style="break-inside: unset;"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang=""><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">1.在驱动代码中定义一个结构体数组，用于描述设备和驱动的匹配规则，其中包含compatible字符串。</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">static const struct of_device_id my_driver_match[] = {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  { .compatible = "vendor,model1" },</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  { .compatible = "vendor,model2" },</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  { },</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">MODULE_DEVICE_TABLE(of, my_driver_match);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">2.在驱动代码中注册设备与驱动的匹配规则。</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">static struct platform_driver my_driver = {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  .probe = my_driver_probe,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  .remove = my_driver_remove,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  .driver = {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  .name = "my_driver",</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  .of_match_table = my_driver_match,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"> &nbsp;  },</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">module_platform_driver(my_driver);</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">3.当内核启动时，会自动进行设备树解析，并使用compatible属性值与驱动代码中的匹配规则进行匹配。</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">如果设备树中的compatible属性值与驱动代码中的匹配规则一致，那么内核会调用相应的驱动probe函数来处理该设备。</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span cm-text="">​</span></span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">注意，设备树节点的compatible属性值必须与驱动代码中定义的匹配规则一致，否则无法成功匹配到对应的驱动。</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 529px;"></div><div class="CodeMirror-gutters" style="display: none; height: 529px;"></div></div></div></pre><p>&nbsp;</p><p><span>匹配的原理</span></p><ol start='' ><li><span>MODULE_DEVICE_TABLE(of, my_driver_match)： 这句代码用于定义并导出一个符号表，表示设备与驱动的匹配规则。该宏会生成一个of_device_id类型的结构体，结构体中包含了设备树节点compatible属性的字符串值。这个符号表将在模块加载时被使用，用于与设备树中的compatible属性进行匹配。</span></li><li><span>module_platform_driver(my_driver)： 这句代码用于注册一个平台驱动（platform driver）。它接受一个struct platform_driver结构体作为参数，其中包含了驱动的操作函数和名称等信息。当模块被加载时，内核会使用这个结构体来初始化驱动，并自动进行设备与驱动的匹配。</span></li></ol><p><span>通过这两句代码的使用，设备与驱动之间建立了匹配关系。当内核解析设备树时，会查找设备树中的compatible属性并与注册的匹配规则进行比较。如果匹配成功，就会调用对应的驱动操作函数来处理该设备。</span></p><p><span>这种机制使得内核能够动态地将设备与驱动关联起来，从而实现设备的自动识别和驱动加载。</span></p><p>&nbsp;</p><h3><a name="31-platform设备驱动实验" class="md-header-anchor"></a><span>3.1 platform设备驱动实验</span></h3><h4><a name="311-驱动的分层与隔离" class="md-header-anchor"></a><span>3.1.1 驱动的分层与隔离</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080120819.png" referrerpolicy="no-referrer" alt="image-20230808012008624"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080121968.png" referrerpolicy="no-referrer" alt="image-20230808012143809"></p><p>&nbsp;</p><h4><a name="312-驱动平台模型" class="md-header-anchor"></a><span>3.1.2 驱动平台模型</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080135006.png" referrerpolicy="no-referrer" alt="image-20230808013542872"></p><p>&nbsp;</p><h5><a name="1）platform总线" class="md-header-anchor"></a><span>1）platform总线</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080139574.png" referrerpolicy="no-referrer" alt="image-20230808013945480"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080141529.png" referrerpolicy="no-referrer" alt="image-20230808014103418"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080142009.png" referrerpolicy="no-referrer" alt="image-20230808014248890"></p><p>&nbsp;</p><h5><a name="2）platform驱动" class="md-header-anchor"></a><span>2）platform驱动</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080148533.png" referrerpolicy="no-referrer" alt="image-20230808014806436"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080149688.png" referrerpolicy="no-referrer" alt="image-20230808014936580"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080152459.png" referrerpolicy="no-referrer" alt="image-20230808015205351"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080153692.png" referrerpolicy="no-referrer" alt="image-20230808015313532"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080153632.png" referrerpolicy="no-referrer" alt="image-20230808015346540"></p><p>&nbsp;</p><p><strong><span>我的理解：</span></strong></p><p><span>假设通过platform平台来驱动一个字符设备。字符设备还是照常创建，也要创建一个platform结构体。在platform结构体中，通过.driver的.name和.of_match_table属性，分别指定名字和of匹配列表，通过.probe和.remove来指定两个函数。（如果匹配成功，platform就会执行）</span></p><p><span>字符设备的初始化，不是在init中完成，而是在probe函数中完成。同理，删除设备，也是在remove函数中完成。</span></p><p><span>在驱动入口init和出口exit函数中，应该进行platform驱动的注册/注销工作。</span></p><p>&nbsp;</p><h5><a name="3）platform设备" class="md-header-anchor"></a><span>3）platform设备</span></h5><p><span>如果内核支持设备树，直接用设备树即可。否则，用platform_device 这个结构体表示 platform 设备。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080202797.png" referrerpolicy="no-referrer" alt="image-20230808020246688"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080208163.png" referrerpolicy="no-referrer" alt="image-20230808020832049"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080210835.png" referrerpolicy="no-referrer" alt="image-20230808021015725"></p><p>&nbsp;</p><p><strong><span>我的理解：</span></strong></p><p><span>和驱动差不多，不过不涉及字符设备的驱动，而是会有对设备资源信息的描述。</span></p><p>&nbsp;</p><p>&nbsp;</p><h4><a name="313-程序编写" class="md-header-anchor"></a><span>3.1.3 程序编写</span></h4><p><span>先写个没用到dts的传统版本。</span></p><h5><a name="1）设备文件" class="md-header-anchor"></a><span>1）设备文件</span></h5><p><span>实际上这个直接通过配置dts可以代替。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080214731.png" referrerpolicy="no-referrer" alt="image-20230808021421624"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080215265.png" referrerpolicy="no-referrer" alt="image-20230808021509167"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080216411.png" referrerpolicy="no-referrer" alt="image-20230808021639313"></p><p>&nbsp;</p><h5><a name="2）驱动文件" class="md-header-anchor"></a><span>2）驱动文件</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080217903.png" referrerpolicy="no-referrer" alt="image-20230808021721811"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080228512.png" referrerpolicy="no-referrer" alt="image-20230808022800398"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080228860.png" referrerpolicy="no-referrer" alt="image-20230808022827772"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080228770.png" referrerpolicy="no-referrer" alt="image-20230808022857676"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080229942.png" referrerpolicy="no-referrer" alt="image-20230808022929835"></p><p>&nbsp;</p><p><strong><span>我的理解：</span></strong></p><p><span>和传统的字符设备驱动的区别在于，在probe 函数和remove函数中执行设备的初始化和删除，寄存器地址是和前面写的设备文件匹配成功后，直接获取的resource。</span></p><p>&nbsp;</p><h5><a name="3）测试程序" class="md-header-anchor"></a><span>3）测试程序</span></h5><p><span>和第四十一章的测试 APP 基本一致。</span></p><p>&nbsp;</p><h4><a name="314-运行测试" class="md-header-anchor"></a><span>3.1.4 运行测试</span></h4><p><span>和前面几乎一样。但是有两个模块（设备+驱动），所以将 obj-m 变量的值改为“leddevice.o leddriver.o”</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080237215.png" referrerpolicy="no-referrer" alt="image-20230808023742103"></p><p>&nbsp;</p><p>&nbsp;</p><h3><a name="32-基于设备树的platform驱动" class="md-header-anchor"></a><span>3.2 基于设备树的platform驱动</span></h3><p><span>在使用设备树的时候，设备的描述被放到了设备树中，因此 platform_device 就不需要我们去编写了，我们只需要实现 platform_driver 即可。</span></p><h4><a name="321-编写注意事项" class="md-header-anchor"></a><span>3.2.1 编写注意事项</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080241027.png" referrerpolicy="no-referrer" alt="image-20230808024121900"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080241008.png" referrerpolicy="no-referrer" alt="image-20230808024149906"></p><p>&nbsp;</p><h4><a name="322-程序编写" class="md-header-anchor"></a><span>3.2.2 程序编写</span></h4><h5><a name="1）设备树-n3173" class="md-header-anchor"></a><span>1）设备树</span></h5><p><span>用之前已经配置过的LED设备树节点就可以了，保持不变，不用改。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080249497.png" referrerpolicy="no-referrer" alt="image-20230808024925402"></p><p>&nbsp;</p><h5><a name="2）驱动程序-n3177" class="md-header-anchor"></a><span>2）驱动程序</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080243493.png" referrerpolicy="no-referrer" alt="image-20230808024315399"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080243523.png" referrerpolicy="no-referrer" alt="image-20230808024341428"></p><p><span>其实驱动的probe和remove函数，就是相当于字符设备驱动的入口/出口函数，进行设备的初始化/删除。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080245201.png" referrerpolicy="no-referrer" alt="image-20230808024521097"></p><p>&nbsp;</p><h5><a name="3）应用程序-n3183" class="md-header-anchor"></a><span>3）应用程序</span></h5><p><span>和上一小节的ledApp一样就可以了。</span></p><p>&nbsp;</p><h4><a name="323-运行测试" class="md-header-anchor"></a><span>3.2.3 运行测试</span></h4><p><span>驱动模块加载完成以后，到/sys/bus/platform/drivers/目录下查看驱动是否存在，</span>
<span>在/sys/bus/platform/devices/目录下也存在 led 的设备文件，也就是设备树中 gpioled 这个节点。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308080255734.png" referrerpolicy="no-referrer" alt="image-20230808025521634"></p><p>&nbsp;</p><p>&nbsp;</p><h3><a name="33-linux自带的led灯驱动实验" class="md-header-anchor"></a><span>3.3 Linux自带的LED灯驱动实验</span></h3><h4><a name="331-linux内核自带led驱动使能" class="md-header-anchor"></a><span>3.3.1 Linux内核自带LED驱动使能</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121019097.png" referrerpolicy="no-referrer" alt="image-20230812101932806"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121020764.png" referrerpolicy="no-referrer" alt="image-20230812102008594"></p><p>&nbsp;</p><h4><a name="332-linux自带led驱动分析" class="md-header-anchor"></a><span>3.3.2 Linux自带LED驱动分析</span></h4><h5><a name="1）驱动框架分析" class="md-header-anchor"></a><span>1）驱动框架分析</span></h5><p><span>LED 灯驱动文件为/drivers/leds/leds-gpio.c</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121021935.png" referrerpolicy="no-referrer" alt="image-20230812102114749"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121021950.png" referrerpolicy="no-referrer" alt="image-20230812102140774"></p><p>&nbsp;</p><h5><a name="2）注册函数moduleplatformdriver分析" class="md-header-anchor"></a><span>2）注册函数module_platform_driver分析</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121025539.png" referrerpolicy="no-referrer" alt="image-20230812102536376"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121026222.png" referrerpolicy="no-referrer" alt="image-20230812102658053"></p><p>&nbsp;</p><h5><a name="3）probe函数-gpioledprobe分析" class="md-header-anchor"></a><span>3）probe函数 gpio_led_probe分析</span></h5><p><span>gpio_led_probe 函数主要功能就是获取 LED 灯的设备信息，然后根据这些信息来初始化对应的 IO，设置为输出等</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121028131.png" referrerpolicy="no-referrer" alt="image-20230812102809026"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121029531.png" referrerpolicy="no-referrer" alt="image-20230812102907404"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121053955.png" referrerpolicy="no-referrer" alt="image-20230812105310740"></p><p>&nbsp;</p><h4><a name="333-设备树节点编写" class="md-header-anchor"></a><span>3.3.3 设备树节点编写</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121054522.png" referrerpolicy="no-referrer" alt="image-20230812105446333"></p><p>&nbsp;</p><h4><a name="334-运行测试" class="md-header-anchor"></a><span>3.3.4 运行测试</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121401717.png" referrerpolicy="no-referrer" alt="image-20230812140117532"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121403902.png" referrerpolicy="no-referrer" alt="image-20230812140335714"></p><p>&nbsp;</p><h3><a name="34-misc驱动实验" class="md-header-anchor"></a><span>3.4 MISC驱动实验</span></h3><h4><a name="341-misc驱动简介" class="md-header-anchor"></a><span>3.4.1 MISC驱动简介</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121505699.png" referrerpolicy="no-referrer" alt="image-20230812150501541"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308121505642.png" referrerpolicy="no-referrer" alt="image-20230812150546536"></p><p>&nbsp;</p><h4><a name="342-代码编写" class="md-header-anchor"></a><span>3.4.2 代码编写</span></h4><h5><a name="1）设备树-n3225" class="md-header-anchor"></a><span>1）设备树</span></h5><p><span>需要用到蜂鸣器，因此需要在 imx6ull-alientek-emmc.dts 文件中创建蜂鸣器设备节点，这里我们直接使用 46.3.1 小节创建的 beep 这个设备节点即可。</span></p><p>&nbsp;</p><h5><a name="2）beep驱动程序编写" class="md-header-anchor"></a><span>2）beep驱动程序编写</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308122037189.png" referrerpolicy="no-referrer" alt="image-20230812203733057"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308122041313.png" referrerpolicy="no-referrer" alt="image-20230812204126186"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308122042862.png" referrerpolicy="no-referrer" alt="image-20230812204213750"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308122124723.png" referrerpolicy="no-referrer" alt="image-20230812212427612"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308122125846.png" referrerpolicy="no-referrer" alt="image-20230812212555715"></p><p>&nbsp;</p><p><span>我的理解：</span></p><ol start='' ><li><span>自己定义了一个 miscbeep_dev 结构体，表示自己定义的设备。</span></li><li><span>定义设备操组函数，用file_operations来指定owner、open、write函数，其中open函数和write函数指向自己定义的函数，在自己定义的write函数中执行写操作。</span></li></ol><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-keyword">struct</span> <span class="cm-def">file_operations</span> <span class="cm-def">miscbeep_fops</span> <span class="cm-operator">=</span> {</span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">owner</span> <span class="cm-operator">=</span> <span class="cm-variable">THIS_MODULE</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">open</span> <span class="cm-operator">=</span> <span class="cm-variable">miscbeep_open</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">write</span> <span class="cm-operator">=</span> <span class="cm-variable">miscbeep_write</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 115px;"></div><div class="CodeMirror-gutters" style="display: none; height: 115px;"></div></div></div></pre><ol start='3' ><li><span>定义一个标准的misc设备结构体，指定它的minor、name和fops，其中fops正是等于前面自己定义的miscbeep_fops/</span></li></ol><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="c"><div class="CodeMirror cm-s-inner CodeMirror-wrap" lang="c"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 8px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;"></textarea></div><div class="CodeMirror-scrollbar-filler" cm-not-content="true"></div><div class="CodeMirror-gutter-filler" cm-not-content="true"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; margin-bottom: 0px; border-right-width: 0px; padding-right: 0px; padding-bottom: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines" role="presentation"><div role="presentation" style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-measure"></div><div style="position: relative; z-index: 1;"></div><div class="CodeMirror-code" role="presentation" style=""><div class="CodeMirror-activeline" style="position: relative;"><div class="CodeMirror-activeline-background CodeMirror-linebackground"></div><div class="CodeMirror-gutter-background CodeMirror-activeline-gutter" style="left: 0px; width: 0px;"></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-comment">/* MISC设备结构体 */</span></span></pre></div><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-keyword">static</span> <span class="cm-keyword">struct</span> <span class="cm-def">miscdevice</span> <span class="cm-def">beep_miscdev</span> <span class="cm-operator">=</span> {</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">minor</span> <span class="cm-operator">=</span> <span class="cm-variable">MISCBEEP_MINOR</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">name</span> <span class="cm-operator">=</span> <span class="cm-variable">MISCBEEP_NAME</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;"><span class="cm-tab" role="presentation" cm-text="	">    </span>.<span class="cm-variable">fops</span> <span class="cm-operator">=</span> <span class="cm-operator">&amp;</span><span class="cm-variable">miscbeep_fops</span>,</span></pre><pre class=" CodeMirror-line " role="presentation"><span role="presentation" style="padding-right: 0.1px;">};</span></pre></div></div></div></div></div><div style="position: absolute; height: 0px; width: 1px; border-bottom: 0px solid transparent; top: 138px;"></div><div class="CodeMirror-gutters" style="display: none; height: 138px;"></div></div></div></pre><ol start='4' ><li><span>编写probe函数和remove函数。</span>
<span>在probe函数里做外设的初始化，最后调用 misc_register(&amp;beep_miscdev) 来注册MISC设备。</span>
<span>在remove函数里用 misc_deregister(&amp;beep_miscdev) 来注销MISC设备。</span></li><li><span>定义platform设备结构体，指定驱动的匹配名字和匹配表，且把probe和remove函数指向自己定义的函数。</span></li><li><span>在驱动的入口和出口处，分别调用platform_driver_register和platform_driver_unregister函数，来对platform结构体进行注册/注销。</span></li></ol><p>&nbsp;</p><h5><a name="3）测试app" class="md-header-anchor"></a><span>3）测试APP</span></h5><p><span>和其它测试APP一样。</span></p><p>&nbsp;</p><h5><a name="4）运行-n3257" class="md-header-anchor"></a><span>4）运行</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130036278.png" referrerpolicy="no-referrer" alt="image-20230813003648125"></p><p>&nbsp;</p><h3><a name="35-linux-input子系统" class="md-header-anchor"></a><span>3.5 Linux input子系统</span></h3><h4><a name="351-input子系统简介" class="md-header-anchor"></a><span>3.5.1 input子系统简介</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130039555.png" referrerpolicy="no-referrer" alt="image-20230813003937430"></p><p>&nbsp;</p><h4><a name="352-input驱动编写流程" class="md-header-anchor"></a><span>3.5.2 input驱动编写流程</span></h4><p><span>input 子系统的所有设备主设备号都为 13，我们在使用 input 子系统处理输入设备的时候就不需要去注册字符设备了，只需要向系统注册一个 input_device 即可。</span></p><h5><a name="1）注册inputdev" class="md-header-anchor"></a><span>1）注册input_dev</span></h5><p><span>我们使用时只需要注册一个input设备。input_dev 结构体表示 input设备，此结构体定义在 include/linux/input.h 文件中，定义如下(有省略)：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130043269.png" referrerpolicy="no-referrer" alt="image-20230813004338143"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130044282.png" referrerpolicy="no-referrer" alt="image-20230813004400151"></p><p><span>综上所述，input_dev的注册过程为：</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130055331.png" referrerpolicy="no-referrer" alt="image-20230813005513234"></p><p><span>示例代码如下。</span></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130057303.png" referrerpolicy="no-referrer" alt="image-20230813005750191"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130058664.png" referrerpolicy="no-referrer" alt="image-20230813005821563"></p><p>&nbsp;</p><h5><a name="2）上报输入事件" class="md-header-anchor"></a><span>2）上报输入事件</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130111661.png" referrerpolicy="no-referrer" alt="image-20230813011120544"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130111504.png" referrerpolicy="no-referrer" alt="image-20230813011159392"></p><p><span>input_report_key，用来上报事件和对应的值（即：是哪个按键按下，有多少按键值）</span></p><p><span>input_sync，用来上报同步事件。</span></p><p>&nbsp;</p><h4><a name="353-inputevent结构体" class="md-header-anchor"></a><span>3.5.3 input_event结构体</span></h4><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130123663.png" referrerpolicy="no-referrer" alt="image-20230813012302563"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130123588.png" referrerpolicy="no-referrer" alt="image-20230813012342489"></p><p>&nbsp;</p><h4><a name="354-代码编写" class="md-header-anchor"></a><span>3.5.4 代码编写</span></h4><h5><a name="1）设备树-n3287" class="md-header-anchor"></a><span>1）设备树</span></h5><p><span>直接使用之前创建的key节点就可以了</span></p><p>&nbsp;</p><h5><a name="2）驱动程序编写" class="md-header-anchor"></a><span>2）驱动程序编写</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130137108.png" referrerpolicy="no-referrer" alt="image-20230813013746011"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130138626.png" referrerpolicy="no-referrer" alt="image-20230813013824533"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130151686.png" referrerpolicy="no-referrer" alt="image-20230813015105579"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130151902.png" referrerpolicy="no-referrer" alt="image-20230813015121806"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130152682.png" referrerpolicy="no-referrer" alt="image-20230813015203585"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130152831.png" referrerpolicy="no-referrer" alt="image-20230813015236725"></p><p><strong><span>我的理解：</span></strong></p><p><span>和自己写的按键驱动差不多，区别在于：</span></p><ol start='' ><li><span>自己定义的设备结构体里，要定义一个input结构体，类型为input_dev。</span></li><li><span>在定时器函数里，使用input_report_key + keydesc 来上报按键的类型和值。（原本的做法是，用atomic_set来改变原子变量的值，用read函数读取）</span></li><li><span>在按键初始化函数（实际在驱动入口函数被调用，就是驱动入口函数）里，申请设备的input_dev，并注册输入设备；在驱动出口函数里，注销输入设备</span></li></ol><p><strong><span>正点原子的解释：</span></strong></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130219004.png" referrerpolicy="no-referrer" alt="image-20230813021930899"></p><p>&nbsp;</p><h5><a name="3）应用程序编写" class="md-header-anchor"></a><span>3）应用程序编写</span></h5><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130220291.png" referrerpolicy="no-referrer" alt="image-20230813022003162"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130221506.png" referrerpolicy="no-referrer" alt="image-20230813022120393"></p><p>&nbsp;</p><h4><a name="355-运行测试" class="md-header-anchor"></a><span>3.5.5 运行测试</span></h4><p><span>编译、挂载部分和之前一样。</span></p><ul><li><span>方法1：自己写驱动程序</span></li></ul><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130227197.png" referrerpolicy="no-referrer" alt="image-20230813022757081"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130227895.png" referrerpolicy="no-referrer" alt="image-20230813022726793"></p><p>&nbsp;</p><ul><li><span>方法2：直接查看</span></li></ul><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130230042.png" referrerpolicy="no-referrer" alt="image-20230813023022922"></p><p><img src="https://gitee.com/yudong-enjoy-coding-777/pic2/raw/master/202308130230408.png" referrerpolicy="no-referrer" alt="image-20230813023043315"></p></div>
</body>
</html>